httparty 0.13.7 → 0.24.2
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.
- checksums.yaml +5 -5
- data/.editorconfig +18 -0
- data/.github/dependabot.yml +6 -0
- data/.github/workflows/ci.yml +24 -0
- data/.gitignore +3 -0
- data/.rubocop_todo.yml +1 -1
- data/Changelog.md +624 -0
- data/Gemfile +11 -3
- data/Guardfile +3 -2
- data/README.md +18 -17
- data/bin/httparty +3 -1
- data/docs/README.md +223 -0
- data/examples/README.md +35 -12
- data/examples/aaws.rb +7 -3
- data/examples/body_stream.rb +14 -0
- data/examples/crack.rb +1 -1
- data/examples/custom_parsers.rb +5 -1
- data/examples/delicious.rb +4 -4
- data/examples/headers_and_user_agents.rb +7 -3
- data/examples/idn.rb +10 -0
- data/examples/logging.rb +4 -4
- data/examples/microsoft_graph.rb +52 -0
- data/examples/multipart.rb +35 -0
- data/examples/party_foul_mode.rb +90 -0
- data/examples/peer_cert.rb +9 -0
- data/examples/stackexchange.rb +1 -1
- data/examples/stream_download.rb +26 -0
- data/examples/tripit_sign_in.rb +17 -6
- data/examples/twitter.rb +2 -2
- data/examples/whoismyrep.rb +1 -1
- data/httparty.gemspec +9 -5
- data/lib/httparty/connection_adapter.rb +71 -24
- data/lib/httparty/cookie_hash.rb +10 -8
- data/lib/httparty/decompressor.rb +102 -0
- data/lib/httparty/exceptions.rb +42 -5
- data/lib/httparty/hash_conversions.rb +30 -8
- data/lib/httparty/headers_processor.rb +32 -0
- data/lib/httparty/logger/apache_formatter.rb +31 -6
- data/lib/httparty/logger/curl_formatter.rb +68 -23
- data/lib/httparty/logger/logger.rb +5 -1
- data/lib/httparty/logger/logstash_formatter.rb +62 -0
- data/lib/httparty/module_inheritable_attributes.rb +9 -9
- data/lib/httparty/net_digest_auth.rb +23 -21
- data/lib/httparty/parser.rb +28 -14
- data/lib/httparty/request/body.rb +125 -0
- data/lib/httparty/request/multipart_boundary.rb +13 -0
- data/lib/httparty/request/streaming_multipart_body.rb +190 -0
- data/lib/httparty/request.rb +224 -122
- data/lib/httparty/response/headers.rb +23 -19
- data/lib/httparty/response.rb +92 -13
- data/lib/httparty/response_fragment.rb +21 -0
- data/lib/httparty/text_encoder.rb +72 -0
- data/lib/httparty/utils.rb +13 -0
- data/lib/httparty/version.rb +3 -1
- data/lib/httparty.rb +118 -42
- data/script/release +4 -4
- data/website/css/common.css +1 -1
- metadata +50 -112
- data/.simplecov +0 -1
- data/.travis.yml +0 -7
- data/History +0 -390
- data/features/basic_authentication.feature +0 -20
- data/features/command_line.feature +0 -95
- data/features/deals_with_http_error_codes.feature +0 -26
- data/features/digest_authentication.feature +0 -30
- data/features/handles_compressed_responses.feature +0 -27
- data/features/handles_multiple_formats.feature +0 -57
- data/features/steps/env.rb +0 -27
- data/features/steps/httparty_response_steps.rb +0 -52
- data/features/steps/httparty_steps.rb +0 -43
- data/features/steps/mongrel_helper.rb +0 -127
- data/features/steps/remote_service_steps.rb +0 -90
- data/features/supports_read_timeout_option.feature +0 -13
- data/features/supports_redirection.feature +0 -22
- data/features/supports_timeout_option.feature +0 -13
- data/spec/fixtures/delicious.xml +0 -23
- data/spec/fixtures/empty.xml +0 -0
- data/spec/fixtures/google.html +0 -3
- data/spec/fixtures/ssl/generate.sh +0 -29
- data/spec/fixtures/ssl/generated/1fe462c2.0 +0 -16
- data/spec/fixtures/ssl/generated/bogushost.crt +0 -13
- data/spec/fixtures/ssl/generated/ca.crt +0 -16
- data/spec/fixtures/ssl/generated/ca.key +0 -15
- data/spec/fixtures/ssl/generated/selfsigned.crt +0 -14
- data/spec/fixtures/ssl/generated/server.crt +0 -13
- data/spec/fixtures/ssl/generated/server.key +0 -15
- data/spec/fixtures/ssl/openssl-exts.cnf +0 -9
- data/spec/fixtures/twitter.csv +0 -2
- data/spec/fixtures/twitter.json +0 -1
- data/spec/fixtures/twitter.xml +0 -403
- data/spec/fixtures/undefined_method_add_node_for_nil.xml +0 -2
- data/spec/httparty/connection_adapter_spec.rb +0 -468
- data/spec/httparty/cookie_hash_spec.rb +0 -83
- data/spec/httparty/exception_spec.rb +0 -38
- data/spec/httparty/hash_conversions_spec.rb +0 -41
- data/spec/httparty/logger/apache_formatter_spec.rb +0 -41
- data/spec/httparty/logger/curl_formatter_spec.rb +0 -18
- data/spec/httparty/logger/logger_spec.rb +0 -38
- data/spec/httparty/net_digest_auth_spec.rb +0 -230
- data/spec/httparty/parser_spec.rb +0 -173
- data/spec/httparty/request_spec.rb +0 -1073
- data/spec/httparty/response_spec.rb +0 -241
- data/spec/httparty/ssl_spec.rb +0 -74
- data/spec/httparty_spec.rb +0 -850
- data/spec/spec_helper.rb +0 -59
- data/spec/support/ssl_test_helper.rb +0 -47
- data/spec/support/ssl_test_server.rb +0 -80
- data/spec/support/stub_response.rb +0 -49
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'erb'
|
|
4
|
+
|
|
1
5
|
module HTTParty
|
|
2
6
|
module HashConversions
|
|
3
7
|
# @return <String> This hash as a query string
|
|
@@ -22,28 +26,46 @@ module HTTParty
|
|
|
22
26
|
#
|
|
23
27
|
# @example normalize_param(:name, "Bob Jones") #=> "name=Bob%20Jones&"
|
|
24
28
|
def self.normalize_param(key, value)
|
|
25
|
-
|
|
29
|
+
normalized_keys = normalize_keys(key, value)
|
|
30
|
+
|
|
31
|
+
normalized_keys.flatten.each_slice(2).inject(''.dup) do |string, (k, v)|
|
|
32
|
+
string << "#{ERB::Util.url_encode(k)}=#{ERB::Util.url_encode(v.to_s)}&"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.normalize_keys(key, value)
|
|
26
37
|
stack = []
|
|
38
|
+
normalized_keys = []
|
|
27
39
|
|
|
28
40
|
if value.respond_to?(:to_ary)
|
|
29
|
-
|
|
41
|
+
if value.empty?
|
|
42
|
+
normalized_keys << ["#{key}[]", '']
|
|
43
|
+
else
|
|
44
|
+
normalized_keys = value.to_ary.flat_map do |element|
|
|
45
|
+
normalize_keys("#{key}[]", element)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
30
48
|
elsif value.respond_to?(:to_hash)
|
|
31
49
|
stack << [key, value.to_hash]
|
|
32
50
|
else
|
|
33
|
-
|
|
51
|
+
normalized_keys << [key.to_s, value]
|
|
34
52
|
end
|
|
35
53
|
|
|
36
54
|
stack.each do |parent, hash|
|
|
37
|
-
hash.each do |
|
|
38
|
-
if
|
|
39
|
-
stack << ["#{parent}[#{
|
|
55
|
+
hash.each do |child_key, child_value|
|
|
56
|
+
if child_value.respond_to?(:to_hash)
|
|
57
|
+
stack << ["#{parent}[#{child_key}]", child_value.to_hash]
|
|
58
|
+
elsif child_value.respond_to?(:to_ary)
|
|
59
|
+
child_value.to_ary.each do |v|
|
|
60
|
+
normalized_keys << normalize_keys("#{parent}[#{child_key}][]", v).flatten
|
|
61
|
+
end
|
|
40
62
|
else
|
|
41
|
-
|
|
63
|
+
normalized_keys << normalize_keys("#{parent}[#{child_key}]", child_value).flatten
|
|
42
64
|
end
|
|
43
65
|
end
|
|
44
66
|
end
|
|
45
67
|
|
|
46
|
-
|
|
68
|
+
normalized_keys
|
|
47
69
|
end
|
|
48
70
|
end
|
|
49
71
|
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module HTTParty
|
|
4
|
+
class HeadersProcessor
|
|
5
|
+
attr_reader :headers, :options
|
|
6
|
+
|
|
7
|
+
def initialize(headers, options)
|
|
8
|
+
@headers = headers
|
|
9
|
+
@options = options
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def call
|
|
13
|
+
return unless options[:headers]
|
|
14
|
+
|
|
15
|
+
options[:headers] = headers.merge(options[:headers]) if headers.any?
|
|
16
|
+
options[:headers] = Utils.stringify_keys(process_dynamic_headers)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def process_dynamic_headers
|
|
22
|
+
options[:headers].each_with_object({}) do |header, processed_headers|
|
|
23
|
+
key, value = header
|
|
24
|
+
processed_headers[key] = if value.respond_to?(:call)
|
|
25
|
+
value.arity == 0 ? value.call : value.call(options)
|
|
26
|
+
else
|
|
27
|
+
value
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module HTTParty
|
|
2
4
|
module Logger
|
|
3
5
|
class ApacheFormatter #:nodoc:
|
|
4
6
|
TAG_NAME = HTTParty.name
|
|
5
7
|
|
|
6
|
-
attr_accessor :level, :logger
|
|
8
|
+
attr_accessor :level, :logger
|
|
7
9
|
|
|
8
10
|
def initialize(logger, level)
|
|
9
11
|
@logger = logger
|
|
@@ -11,11 +13,34 @@ module HTTParty
|
|
|
11
13
|
end
|
|
12
14
|
|
|
13
15
|
def format(request, response)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
@request = request
|
|
17
|
+
@response = response
|
|
18
|
+
|
|
19
|
+
logger.public_send level, message
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
attr_reader :request, :response
|
|
25
|
+
|
|
26
|
+
def message
|
|
27
|
+
"[#{TAG_NAME}] [#{current_time}] #{response.code} \"#{http_method} #{path}\" #{content_length || '-'} "
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def current_time
|
|
31
|
+
Time.now.strftime('%Y-%m-%d %H:%M:%S %z')
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def http_method
|
|
35
|
+
request.http_method.name.split('::').last.upcase
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def path
|
|
39
|
+
request.path.to_s
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def content_length
|
|
43
|
+
response.respond_to?(:headers) ? response.headers['Content-Length'] : response['Content-Length']
|
|
19
44
|
end
|
|
20
45
|
end
|
|
21
46
|
end
|
|
@@ -1,47 +1,92 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module HTTParty
|
|
2
4
|
module Logger
|
|
3
5
|
class CurlFormatter #:nodoc:
|
|
4
6
|
TAG_NAME = HTTParty.name
|
|
5
|
-
OUT
|
|
6
|
-
IN
|
|
7
|
+
OUT = '>'
|
|
8
|
+
IN = '<'
|
|
7
9
|
|
|
8
|
-
attr_accessor :level, :logger
|
|
10
|
+
attr_accessor :level, :logger
|
|
9
11
|
|
|
10
12
|
def initialize(logger, level)
|
|
11
|
-
@logger
|
|
12
|
-
@level
|
|
13
|
+
@logger = logger
|
|
14
|
+
@level = level.to_sym
|
|
15
|
+
@messages = []
|
|
13
16
|
end
|
|
14
17
|
|
|
15
18
|
def format(request, response)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
http_method = request.http_method.name.split("::").last.upcase
|
|
19
|
-
path = request.path.to_s
|
|
19
|
+
@request = request
|
|
20
|
+
@response = response
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
log_request
|
|
23
|
+
log_response
|
|
22
24
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
logger.public_send level, messages.join("\n")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
attr_reader :request, :response
|
|
31
|
+
attr_accessor :messages
|
|
28
32
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
def log_request
|
|
34
|
+
log_url
|
|
35
|
+
log_headers
|
|
36
|
+
log_query
|
|
37
|
+
log OUT, request.raw_body if request.raw_body
|
|
38
|
+
log OUT
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def log_response
|
|
42
|
+
log IN, "HTTP/#{response.http_version} #{response.code}"
|
|
43
|
+
log_response_headers
|
|
44
|
+
log IN, "\n#{response.body}"
|
|
45
|
+
log IN
|
|
46
|
+
end
|
|
32
47
|
|
|
48
|
+
def log_url
|
|
49
|
+
http_method = request.http_method.name.split('::').last.upcase
|
|
50
|
+
uri = if request.options[:base_uri]
|
|
51
|
+
request.options[:base_uri] + request.path.path
|
|
52
|
+
else
|
|
53
|
+
request.path.to_s
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
log OUT, "#{http_method} #{uri}"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def log_headers
|
|
60
|
+
return unless request.options[:headers] && request.options[:headers].size > 0
|
|
61
|
+
|
|
62
|
+
log OUT, 'Headers: '
|
|
63
|
+
log_hash request.options[:headers]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def log_query
|
|
67
|
+
return unless request.options[:query]
|
|
68
|
+
|
|
69
|
+
log OUT, 'Query: '
|
|
70
|
+
log_hash request.options[:query]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def log_response_headers
|
|
33
74
|
headers = response.respond_to?(:headers) ? response.headers : response
|
|
34
75
|
response.each_header do |response_header|
|
|
35
|
-
|
|
76
|
+
log IN, "#{response_header.capitalize}: #{headers[response_header]}"
|
|
36
77
|
end
|
|
78
|
+
end
|
|
37
79
|
|
|
38
|
-
|
|
80
|
+
def log_hash(hash)
|
|
81
|
+
hash.each { |k, v| log(OUT, "#{k}: #{v}") }
|
|
82
|
+
end
|
|
39
83
|
|
|
40
|
-
|
|
84
|
+
def log(direction, line = '')
|
|
85
|
+
messages << "[#{TAG_NAME}] [#{current_time}] #{direction} #{line}"
|
|
41
86
|
end
|
|
42
87
|
|
|
43
|
-
def
|
|
44
|
-
"
|
|
88
|
+
def current_time
|
|
89
|
+
Time.now.strftime("%Y-%m-%d %H:%M:%S %z")
|
|
45
90
|
end
|
|
46
91
|
end
|
|
47
92
|
end
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'httparty/logger/apache_formatter'
|
|
2
4
|
require 'httparty/logger/curl_formatter'
|
|
5
|
+
require 'httparty/logger/logstash_formatter'
|
|
3
6
|
|
|
4
7
|
module HTTParty
|
|
5
8
|
module Logger
|
|
6
9
|
def self.formatters
|
|
7
10
|
@formatters ||= {
|
|
8
11
|
:curl => Logger::CurlFormatter,
|
|
9
|
-
:apache => Logger::ApacheFormatter
|
|
12
|
+
:apache => Logger::ApacheFormatter,
|
|
13
|
+
:logstash => Logger::LogstashFormatter,
|
|
10
14
|
}
|
|
11
15
|
end
|
|
12
16
|
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module HTTParty
|
|
4
|
+
module Logger
|
|
5
|
+
class LogstashFormatter #:nodoc:
|
|
6
|
+
TAG_NAME = HTTParty.name
|
|
7
|
+
|
|
8
|
+
attr_accessor :level, :logger
|
|
9
|
+
|
|
10
|
+
def initialize(logger, level)
|
|
11
|
+
@logger = logger
|
|
12
|
+
@level = level.to_sym
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def format(request, response)
|
|
16
|
+
@request = request
|
|
17
|
+
@response = response
|
|
18
|
+
|
|
19
|
+
logger.public_send level, logstash_message
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
attr_reader :request, :response
|
|
25
|
+
|
|
26
|
+
def logstash_message
|
|
27
|
+
require 'json'
|
|
28
|
+
{
|
|
29
|
+
'@timestamp' => current_time,
|
|
30
|
+
'@version' => 1,
|
|
31
|
+
'content_length' => content_length || '-',
|
|
32
|
+
'http_method' => http_method,
|
|
33
|
+
'message' => message,
|
|
34
|
+
'path' => path,
|
|
35
|
+
'response_code' => response.code,
|
|
36
|
+
'severity' => level,
|
|
37
|
+
'tags' => [TAG_NAME],
|
|
38
|
+
}.to_json
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def message
|
|
42
|
+
"[#{TAG_NAME}] #{response.code} \"#{http_method} #{path}\" #{content_length || '-'} "
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def current_time
|
|
46
|
+
Time.now.strftime('%Y-%m-%d %H:%M:%S %z')
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def http_method
|
|
50
|
+
@http_method ||= request.http_method.name.split('::').last.upcase
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def path
|
|
54
|
+
@path ||= request.path.to_s
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def content_length
|
|
58
|
+
@content_length ||= response.respond_to?(:headers) ? response.headers['Content-Length'] : response['Content-Length']
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module HTTParty
|
|
2
4
|
module ModuleInheritableAttributes #:nodoc:
|
|
3
5
|
def self.included(base)
|
|
@@ -9,12 +11,12 @@ module HTTParty
|
|
|
9
11
|
duplicate = hash.dup
|
|
10
12
|
|
|
11
13
|
duplicate.each_pair do |key, value|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
if value.is_a?(Hash)
|
|
15
|
+
duplicate[key] = hash_deep_dup(value)
|
|
14
16
|
elsif value.is_a?(Proc)
|
|
15
17
|
duplicate[key] = value.dup
|
|
16
18
|
else
|
|
17
|
-
value
|
|
19
|
+
duplicate[key] = value
|
|
18
20
|
end
|
|
19
21
|
end
|
|
20
22
|
|
|
@@ -27,7 +29,7 @@ module HTTParty
|
|
|
27
29
|
@mattr_inheritable_attrs += args
|
|
28
30
|
|
|
29
31
|
args.each do |arg|
|
|
30
|
-
|
|
32
|
+
singleton_class.attr_accessor(arg)
|
|
31
33
|
end
|
|
32
34
|
|
|
33
35
|
@mattr_inheritable_attrs
|
|
@@ -36,18 +38,16 @@ module HTTParty
|
|
|
36
38
|
def inherited(subclass)
|
|
37
39
|
super
|
|
38
40
|
@mattr_inheritable_attrs.each do |inheritable_attribute|
|
|
39
|
-
ivar = "@#{inheritable_attribute}"
|
|
41
|
+
ivar = :"@#{inheritable_attribute}"
|
|
40
42
|
subclass.instance_variable_set(ivar, instance_variable_get(ivar).clone)
|
|
41
43
|
|
|
42
44
|
if instance_variable_get(ivar).respond_to?(:merge)
|
|
43
|
-
|
|
45
|
+
subclass.class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
|
44
46
|
def self.#{inheritable_attribute}
|
|
45
47
|
duplicate = ModuleInheritableAttributes.hash_deep_dup(#{ivar})
|
|
46
48
|
#{ivar} = superclass.#{inheritable_attribute}.merge(duplicate)
|
|
47
49
|
end
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
subclass.class_eval method
|
|
50
|
+
RUBY
|
|
51
51
|
end
|
|
52
52
|
end
|
|
53
53
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'digest/md5'
|
|
2
4
|
require 'net/http'
|
|
3
5
|
|
|
@@ -12,13 +14,13 @@ module Net
|
|
|
12
14
|
response
|
|
13
15
|
)
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
authenticator.authorization_header.each do |v|
|
|
18
|
+
add_field('Authorization', v)
|
|
19
|
+
end
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
authenticator.cookie_header.each do |v|
|
|
22
|
+
add_field('Cookie', v)
|
|
23
|
+
end
|
|
22
24
|
end
|
|
23
25
|
|
|
24
26
|
class DigestAuthenticator
|
|
@@ -44,12 +46,9 @@ module Net
|
|
|
44
46
|
header << %(algorithm="#{@response['algorithm']}") if algorithm_present?
|
|
45
47
|
|
|
46
48
|
if qop_present?
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
"nc=00000001"
|
|
51
|
-
]
|
|
52
|
-
fields.each { |field| header << field }
|
|
49
|
+
header << %(cnonce="#{@cnonce}")
|
|
50
|
+
header << %(qop="#{@response['qop']}")
|
|
51
|
+
header << 'nc=00000001'
|
|
53
52
|
end
|
|
54
53
|
|
|
55
54
|
header << %(opaque="#{@response['opaque']}") if opaque_present?
|
|
@@ -64,12 +63,15 @@ module Net
|
|
|
64
63
|
|
|
65
64
|
def parse(response_header)
|
|
66
65
|
header = response_header['www-authenticate']
|
|
67
|
-
|
|
66
|
+
|
|
67
|
+
header = header.gsub(/qop=(auth(?:-int)?)/, 'qop="\\1"')
|
|
68
68
|
|
|
69
69
|
header =~ /Digest (.*)/
|
|
70
70
|
params = {}
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
if $1
|
|
72
|
+
non_quoted = $1.gsub(/(\w+)="(.*?)"/) { params[$1] = $2 }
|
|
73
|
+
non_quoted.gsub(/(\w+)=([^,]*)/) { params[$1] = $2 }
|
|
74
|
+
end
|
|
73
75
|
params
|
|
74
76
|
end
|
|
75
77
|
|
|
@@ -95,13 +97,13 @@ module Net
|
|
|
95
97
|
end
|
|
96
98
|
|
|
97
99
|
def random
|
|
98
|
-
format
|
|
100
|
+
format '%x', (Time.now.to_i + rand(65535))
|
|
99
101
|
end
|
|
100
102
|
|
|
101
103
|
def request_digest
|
|
102
104
|
a = [md5(a1), @response['nonce'], md5(a2)]
|
|
103
|
-
a.insert(2,
|
|
104
|
-
md5(a.join(
|
|
105
|
+
a.insert(2, '00000001', @cnonce, @response['qop']) if qop_present?
|
|
106
|
+
md5(a.join(':'))
|
|
105
107
|
end
|
|
106
108
|
|
|
107
109
|
def md5(str)
|
|
@@ -111,11 +113,11 @@ module Net
|
|
|
111
113
|
def algorithm_present?
|
|
112
114
|
@response.key?('algorithm') && !@response['algorithm'].empty?
|
|
113
115
|
end
|
|
114
|
-
|
|
116
|
+
|
|
115
117
|
def use_md5_sess?
|
|
116
118
|
algorithm_present? && @response['algorithm'] == 'MD5-sess'
|
|
117
119
|
end
|
|
118
|
-
|
|
120
|
+
|
|
119
121
|
def a1
|
|
120
122
|
a1_user_realm_pwd = [@username, @response['realm'], @password].join(':')
|
|
121
123
|
if use_md5_sess?
|
|
@@ -126,7 +128,7 @@ module Net
|
|
|
126
128
|
end
|
|
127
129
|
|
|
128
130
|
def a2
|
|
129
|
-
[@method, @path].join(
|
|
131
|
+
[@method, @path].join(':')
|
|
130
132
|
end
|
|
131
133
|
end
|
|
132
134
|
end
|
data/lib/httparty/parser.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module HTTParty
|
|
2
4
|
# The default parser used by HTTParty, supports xml, json, html, csv and
|
|
3
5
|
# plain text.
|
|
@@ -38,16 +40,18 @@ module HTTParty
|
|
|
38
40
|
# @abstract Read the Custom Parsers section for more information.
|
|
39
41
|
class Parser
|
|
40
42
|
SupportedFormats = {
|
|
41
|
-
'text/xml'
|
|
42
|
-
'application/xml'
|
|
43
|
-
'application/json'
|
|
44
|
-
'
|
|
45
|
-
'application/
|
|
46
|
-
'text/
|
|
47
|
-
'
|
|
48
|
-
'text/
|
|
49
|
-
'text/
|
|
50
|
-
'
|
|
43
|
+
'text/xml' => :xml,
|
|
44
|
+
'application/xml' => :xml,
|
|
45
|
+
'application/json' => :json,
|
|
46
|
+
'application/vnd.api+json' => :json,
|
|
47
|
+
'application/hal+json' => :json,
|
|
48
|
+
'text/json' => :json,
|
|
49
|
+
'application/javascript' => :plain,
|
|
50
|
+
'text/javascript' => :plain,
|
|
51
|
+
'text/html' => :html,
|
|
52
|
+
'text/plain' => :plain,
|
|
53
|
+
'text/csv' => :csv,
|
|
54
|
+
'application/csv' => :csv,
|
|
51
55
|
'text/comma-separated-values' => :csv
|
|
52
56
|
}
|
|
53
57
|
|
|
@@ -99,8 +103,11 @@ module HTTParty
|
|
|
99
103
|
# @return [nil] when the response body is nil, an empty string, spaces only or "null"
|
|
100
104
|
def parse
|
|
101
105
|
return nil if body.nil?
|
|
102
|
-
return nil if body ==
|
|
106
|
+
return nil if body == 'null'
|
|
103
107
|
return nil if body.valid_encoding? && body.strip.empty?
|
|
108
|
+
if body.valid_encoding? && body.encoding == Encoding::UTF_8
|
|
109
|
+
@body = body.gsub(/\A#{UTF8_BOM}/, '')
|
|
110
|
+
end
|
|
104
111
|
if supports_format?
|
|
105
112
|
parse_supported_format
|
|
106
113
|
else
|
|
@@ -111,14 +118,19 @@ module HTTParty
|
|
|
111
118
|
protected
|
|
112
119
|
|
|
113
120
|
def xml
|
|
121
|
+
require 'multi_xml'
|
|
114
122
|
MultiXml.parse(body)
|
|
115
123
|
end
|
|
116
124
|
|
|
125
|
+
UTF8_BOM = "\xEF\xBB\xBF"
|
|
126
|
+
|
|
117
127
|
def json
|
|
128
|
+
require 'json'
|
|
118
129
|
JSON.parse(body, :quirks_mode => true, :allow_nan => true)
|
|
119
130
|
end
|
|
120
131
|
|
|
121
132
|
def csv
|
|
133
|
+
require 'csv'
|
|
122
134
|
CSV.parse(body)
|
|
123
135
|
end
|
|
124
136
|
|
|
@@ -135,9 +147,11 @@ module HTTParty
|
|
|
135
147
|
end
|
|
136
148
|
|
|
137
149
|
def parse_supported_format
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
150
|
+
if respond_to?(format, true)
|
|
151
|
+
send(format)
|
|
152
|
+
else
|
|
153
|
+
raise NotImplementedError, "#{self.class.name} has not implemented a parsing method for the #{format.inspect} format."
|
|
154
|
+
end
|
|
141
155
|
end
|
|
142
156
|
end
|
|
143
157
|
end
|