httparty 0.10.0 → 0.14.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 (79) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +92 -0
  4. data/.rubocop_todo.yml +124 -0
  5. data/.simplecov +1 -0
  6. data/.travis.yml +5 -4
  7. data/CONTRIBUTING.md +23 -0
  8. data/Gemfile +9 -5
  9. data/Guardfile +3 -3
  10. data/History +109 -8
  11. data/README.md +21 -21
  12. data/Rakefile +5 -10
  13. data/bin/httparty +21 -14
  14. data/docs/README.md +100 -0
  15. data/examples/README.md +67 -0
  16. data/examples/aaws.rb +9 -9
  17. data/examples/basic.rb +6 -10
  18. data/examples/crack.rb +3 -3
  19. data/examples/custom_parsers.rb +1 -4
  20. data/examples/delicious.rb +12 -12
  21. data/examples/google.rb +2 -2
  22. data/examples/headers_and_user_agents.rb +2 -2
  23. data/examples/logging.rb +36 -0
  24. data/examples/nokogiri_html_parser.rb +0 -3
  25. data/examples/rescue_json.rb +17 -0
  26. data/examples/rubyurl.rb +3 -3
  27. data/examples/stackexchange.rb +24 -0
  28. data/examples/tripit_sign_in.rb +20 -9
  29. data/examples/twitter.rb +11 -11
  30. data/examples/whoismyrep.rb +2 -2
  31. data/features/command_line.feature +90 -2
  32. data/features/digest_authentication.feature +10 -0
  33. data/features/handles_compressed_responses.feature +8 -0
  34. data/features/handles_multiple_formats.feature +23 -0
  35. data/features/steps/env.rb +16 -11
  36. data/features/steps/httparty_response_steps.rb +40 -10
  37. data/features/steps/httparty_steps.rb +19 -3
  38. data/features/steps/mongrel_helper.rb +35 -2
  39. data/features/steps/remote_service_steps.rb +31 -8
  40. data/features/supports_read_timeout_option.feature +13 -0
  41. data/httparty.gemspec +9 -6
  42. data/lib/httparty/connection_adapter.rb +76 -11
  43. data/lib/httparty/cookie_hash.rb +3 -4
  44. data/lib/httparty/exceptions.rb +10 -4
  45. data/lib/httparty/hash_conversions.rb +19 -17
  46. data/lib/httparty/logger/apache_formatter.rb +22 -0
  47. data/lib/httparty/logger/curl_formatter.rb +91 -0
  48. data/lib/httparty/logger/logger.rb +26 -0
  49. data/lib/httparty/module_inheritable_attributes.rb +1 -1
  50. data/lib/httparty/net_digest_auth.rb +69 -18
  51. data/lib/httparty/parser.rb +15 -11
  52. data/lib/httparty/request.rb +186 -47
  53. data/lib/httparty/response/headers.rb +2 -2
  54. data/lib/httparty/response.rb +44 -9
  55. data/lib/httparty/version.rb +1 -1
  56. data/lib/httparty.rb +187 -65
  57. data/script/release +42 -0
  58. data/spec/fixtures/twitter.csv +2 -0
  59. data/spec/httparty/connection_adapter_spec.rb +334 -62
  60. data/spec/httparty/cookie_hash_spec.rb +53 -23
  61. data/spec/httparty/exception_spec.rb +45 -0
  62. data/spec/httparty/hash_conversions_spec.rb +49 -0
  63. data/spec/httparty/logger/apache_formatter_spec.rb +41 -0
  64. data/spec/httparty/logger/curl_formatter_spec.rb +119 -0
  65. data/spec/httparty/logger/logger_spec.rb +38 -0
  66. data/spec/httparty/net_digest_auth_spec.rb +148 -23
  67. data/spec/httparty/parser_spec.rb +48 -41
  68. data/spec/httparty/request_spec.rb +845 -151
  69. data/spec/httparty/response_spec.rb +147 -70
  70. data/spec/httparty/ssl_spec.rb +33 -21
  71. data/spec/httparty_spec.rb +337 -186
  72. data/spec/spec_helper.rb +38 -9
  73. data/spec/support/ssl_test_helper.rb +10 -10
  74. data/spec/support/ssl_test_server.rb +21 -21
  75. data/spec/support/stub_response.rb +20 -14
  76. data/website/index.html +3 -3
  77. metadata +46 -37
  78. data/lib/httparty/core_extensions.rb +0 -32
  79. data/spec/spec.opts +0 -2
@@ -0,0 +1,45 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ RSpec.describe HTTParty::Error do
4
+ subject { described_class }
5
+
6
+ describe '#ancestors' do
7
+ subject { super().ancestors }
8
+ it { is_expected.to include(StandardError) }
9
+ end
10
+
11
+ describe HTTParty::UnsupportedFormat do
12
+ describe '#ancestors' do
13
+ subject { super().ancestors }
14
+ it { is_expected.to include(HTTParty::Error) }
15
+ end
16
+ end
17
+
18
+ describe HTTParty::UnsupportedURIScheme do
19
+ describe '#ancestors' do
20
+ subject { super().ancestors }
21
+ it { is_expected.to include(HTTParty::Error) }
22
+ end
23
+ end
24
+
25
+ describe HTTParty::ResponseError do
26
+ describe '#ancestors' do
27
+ subject { super().ancestors }
28
+ it { is_expected.to include(HTTParty::Error) }
29
+ end
30
+ end
31
+
32
+ describe HTTParty::RedirectionTooDeep do
33
+ describe '#ancestors' do
34
+ subject { super().ancestors }
35
+ it { is_expected.to include(HTTParty::ResponseError) }
36
+ end
37
+ end
38
+
39
+ describe HTTParty::DuplicateLocationHeader do
40
+ describe '#ancestors' do
41
+ subject { super().ancestors }
42
+ it { is_expected.to include(HTTParty::ResponseError) }
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,49 @@
1
+ RSpec.describe HTTParty::HashConversions do
2
+ describe ".to_params" do
3
+ it "creates a params string from a hash" do
4
+ hash = {
5
+ name: "bob",
6
+ address: {
7
+ street: '111 ruby ave.',
8
+ city: 'ruby central',
9
+ phones: ['111-111-1111', '222-222-2222']
10
+ }
11
+ }
12
+ expect(HTTParty::HashConversions.to_params(hash)).to eq("name=bob&address[street]=111%20ruby%20ave.&address[city]=ruby%20central&address[phones][]=111-111-1111&address[phones][]=222-222-2222")
13
+ end
14
+ end
15
+
16
+ describe ".normalize_param" do
17
+ context "value is an array" do
18
+ it "creates a params string" do
19
+ expect(
20
+ HTTParty::HashConversions.normalize_param(:people, ["Bob Jones", "Mike Smith"])
21
+ ).to eq("people[]=Bob%20Jones&people[]=Mike%20Smith&")
22
+ end
23
+ end
24
+
25
+ context "value is an empty array" do
26
+ it "creates a params string" do
27
+ expect(
28
+ HTTParty::HashConversions.normalize_param(:people, [])
29
+ ).to eq("people[]=&")
30
+ end
31
+ end
32
+
33
+ context "value is hash" do
34
+ it "creates a params string" do
35
+ expect(
36
+ HTTParty::HashConversions.normalize_param(:person, { name: "Bob Jones" })
37
+ ).to eq("person[name]=Bob%20Jones&")
38
+ end
39
+ end
40
+
41
+ context "value is a string" do
42
+ it "creates a params string" do
43
+ expect(
44
+ HTTParty::HashConversions.normalize_param(:name, "Bob Jones")
45
+ ).to eq("name=Bob%20Jones&")
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,41 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
2
+
3
+ RSpec.describe HTTParty::Logger::ApacheFormatter do
4
+ let(:subject) { described_class.new(logger_double, :info) }
5
+ let(:logger_double) { double('Logger') }
6
+ let(:request_double) { double('Request', http_method: Net::HTTP::Get, path: "http://my.domain.com/my_path") }
7
+ let(:request_time) { Time.new.strftime("%Y-%m-%d %H:%M:%S %z") }
8
+
9
+ before do
10
+ subject.current_time = request_time
11
+ expect(logger_double).to receive(:info).with(log_message)
12
+ end
13
+
14
+ describe "#format" do
15
+ let(:log_message) { "[HTTParty] [#{request_time}] 302 \"GET http://my.domain.com/my_path\" - " }
16
+
17
+ it "formats a response in a style that resembles apache's access log" do
18
+ response_double = double(
19
+ code: 302,
20
+ :[] => nil
21
+ )
22
+
23
+ subject.format(request_double, response_double)
24
+ end
25
+
26
+ context 'when there is a parsed response' do
27
+ let(:log_message) { "[HTTParty] [#{request_time}] 200 \"GET http://my.domain.com/my_path\" 512 "}
28
+
29
+ it "can handle the Content-Length header" do
30
+ # Simulate a parsed response that is an array, where accessing a string key will raise an error. See Issue #299.
31
+ response_double = double(
32
+ code: 200,
33
+ headers: { 'Content-Length' => 512 }
34
+ )
35
+ allow(response_double).to receive(:[]).with('Content-Length').and_raise(TypeError.new('no implicit conversion of String into Integer'))
36
+
37
+ subject.format(request_double, response_double)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,119 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
2
+
3
+ RSpec.describe HTTParty::Logger::CurlFormatter do
4
+ describe "#format" do
5
+ let(:logger) { double('Logger') }
6
+ let(:response_object) { Net::HTTPOK.new('1.1', 200, 'OK') }
7
+ let(:parsed_response) { lambda { {"foo" => "bar"} } }
8
+
9
+ let(:response) do
10
+ HTTParty::Response.new(request, response_object, parsed_response)
11
+ end
12
+
13
+ let(:request) do
14
+ HTTParty::Request.new(Net::HTTP::Get, 'http://foo.bar.com/')
15
+ end
16
+
17
+ subject { described_class.new(logger, :info) }
18
+
19
+ before do
20
+ allow(logger).to receive(:info)
21
+ allow(request).to receive(:raw_body).and_return('content')
22
+ allow(response_object).to receive_messages(body: "{foo:'bar'}")
23
+ response_object['header-key'] = 'header-value'
24
+
25
+ subject.format request, response
26
+ end
27
+
28
+ context 'when request is logged' do
29
+ context "and request's option 'base_uri' is not present" do
30
+ it 'logs url' do
31
+ expect(logger).to have_received(:info).with(/\[HTTParty\] \[\d{4}-\d\d-\d\d \d\d:\d\d:\d\d\ [+-]\d{4}\] > GET http:\/\/foo.bar.com/)
32
+ end
33
+ end
34
+
35
+ context "and request's option 'base_uri' is present" do
36
+ let(:request) do
37
+ HTTParty::Request.new(Net::HTTP::Get, '/path', base_uri: 'http://foo.bar.com')
38
+ end
39
+
40
+ it 'logs url' do
41
+ expect(logger).to have_received(:info).with(/\[HTTParty\] \[\d{4}-\d\d-\d\d \d\d:\d\d:\d\d\ [+-]\d{4}\] > GET http:\/\/foo.bar.com\/path/)
42
+ end
43
+ end
44
+
45
+ context 'and headers are not present' do
46
+ it 'not log Headers' do
47
+ expect(logger).not_to have_received(:info).with(/Headers/)
48
+ end
49
+ end
50
+
51
+ context 'and headers are present' do
52
+ let(:request) do
53
+ HTTParty::Request.new(Net::HTTP::Get, '/path', base_uri: 'http://foo.bar.com', headers: { key: 'value' })
54
+ end
55
+
56
+ it 'logs Headers' do
57
+ expect(logger).to have_received(:info).with(/Headers/)
58
+ end
59
+
60
+ it 'logs headers keys' do
61
+ expect(logger).to have_received(:info).with(/key: value/)
62
+ end
63
+ end
64
+
65
+ context 'and query is not present' do
66
+ it 'not logs Query' do
67
+ expect(logger).not_to have_received(:info).with(/Query/)
68
+ end
69
+ end
70
+
71
+ context 'and query is present' do
72
+ let(:request) do
73
+ HTTParty::Request.new(Net::HTTP::Get, '/path', query: { key: 'value' })
74
+ end
75
+
76
+ it 'logs Query' do
77
+ expect(logger).to have_received(:info).with(/Query/)
78
+ end
79
+
80
+ it 'logs query params' do
81
+ expect(logger).to have_received(:info).with(/key: value/)
82
+ end
83
+ end
84
+
85
+ context 'when request raw_body is present' do
86
+ it 'not logs request body' do
87
+ expect(logger).to have_received(:info).with(/content/)
88
+ end
89
+ end
90
+ end
91
+
92
+ context 'when response is logged' do
93
+ it 'logs http version and response code' do
94
+ expect(logger).to have_received(:info).with(/HTTP\/1.1 200/)
95
+ end
96
+
97
+ it 'logs headers' do
98
+ expect(logger).to have_received(:info).with(/Header-key: header-value/)
99
+ end
100
+
101
+ it 'logs body' do
102
+ expect(logger).to have_received(:info).with(/{foo:'bar'}/)
103
+ end
104
+ end
105
+
106
+ it "formats a response in a style that resembles a -v curl" do
107
+ logger_double = double
108
+ expect(logger_double).to receive(:info).with(
109
+ /\[HTTParty\] \[\d{4}-\d\d-\d\d \d\d:\d\d:\d\d\ [+-]\d{4}\] > GET http:\/\/localhost/)
110
+
111
+ subject = described_class.new(logger_double, :info)
112
+
113
+ stub_http_response_with("google.html")
114
+
115
+ response = HTTParty::Request.new.perform
116
+ subject.format(response.request, response)
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,38 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
2
+
3
+ RSpec.describe HTTParty::Logger do
4
+ describe ".build" do
5
+ subject { HTTParty::Logger }
6
+
7
+ it "defaults level to :info" do
8
+ logger_double = double
9
+ expect(subject.build(logger_double, nil, nil).level).to eq(:info)
10
+ end
11
+
12
+ it "defaults format to :apache" do
13
+ logger_double = double
14
+ expect(subject.build(logger_double, nil, nil)).to be_an_instance_of(HTTParty::Logger::ApacheFormatter)
15
+ end
16
+
17
+ it "builds :curl style logger" do
18
+ logger_double = double
19
+ expect(subject.build(logger_double, nil, :curl)).to be_an_instance_of(HTTParty::Logger::CurlFormatter)
20
+ end
21
+
22
+ it "builds :custom style logger" do
23
+ CustomFormatter = Class.new(HTTParty::Logger::CurlFormatter)
24
+ HTTParty::Logger.add_formatter(:custom, CustomFormatter)
25
+
26
+ logger_double = double
27
+ expect(subject.build(logger_double, nil, :custom)).
28
+ to be_an_instance_of(CustomFormatter)
29
+ end
30
+ it "raises error when formatter exists" do
31
+ CustomFormatter2= Class.new(HTTParty::Logger::CurlFormatter)
32
+ HTTParty::Logger.add_formatter(:custom2, CustomFormatter2)
33
+
34
+ expect{ HTTParty::Logger.add_formatter(:custom2, CustomFormatter2) }.
35
+ to raise_error HTTParty::Error
36
+ end
37
+ end
38
+ end
@@ -1,11 +1,11 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
2
 
3
- describe Net::HTTPHeader::DigestAuthenticator do
3
+ RSpec.describe Net::HTTPHeader::DigestAuthenticator do
4
4
  def setup_digest(response)
5
5
  digest = Net::HTTPHeader::DigestAuthenticator.new("Mufasa",
6
- "Circle Of Life", "GET", "/dir/index.html", response)
7
- digest.stub(:random).and_return("deadbeef")
8
- Digest::MD5.stub(:hexdigest) { |str| "md5(#{str})" }
6
+ "Circle Of Life", "GET", "/dir/index.html", response)
7
+ allow(digest).to receive(:random).and_return("deadbeef")
8
+ allow(Digest::MD5).to receive(:hexdigest) { |str| "md5(#{str})" }
9
9
  digest
10
10
  end
11
11
 
@@ -13,6 +13,34 @@ describe Net::HTTPHeader::DigestAuthenticator do
13
13
  @digest.authorization_header.join(", ")
14
14
  end
15
15
 
16
+ def cookie_header
17
+ @digest.cookie_header
18
+ end
19
+
20
+ context "with a cookie value in the response header" do
21
+ before do
22
+ @digest = setup_digest({
23
+ 'www-authenticate' => 'Digest realm="myhost@testrealm.com"',
24
+ 'Set-Cookie' => 'custom-cookie=1234567'
25
+ })
26
+ end
27
+
28
+ it "should set cookie header" do
29
+ expect(cookie_header).to include('custom-cookie=1234567')
30
+ end
31
+ end
32
+
33
+ context "without a cookie value in the response header" do
34
+ before do
35
+ @digest = setup_digest({
36
+ 'www-authenticate' => 'Digest realm="myhost@testrealm.com"'
37
+ })
38
+ end
39
+
40
+ it "should set empty cookie header array" do
41
+ expect(cookie_header).to eql []
42
+ end
43
+ end
16
44
 
17
45
  context "with an opaque value in the response header" do
18
46
  before do
@@ -22,7 +50,7 @@ describe Net::HTTPHeader::DigestAuthenticator do
22
50
  end
23
51
 
24
52
  it "should set opaque" do
25
- authorization_header.should include(%Q(opaque="solid"))
53
+ expect(authorization_header).to include('opaque="solid"')
26
54
  end
27
55
  end
28
56
 
@@ -30,86 +58,183 @@ describe Net::HTTPHeader::DigestAuthenticator do
30
58
  before do
31
59
  @digest = setup_digest({
32
60
  'www-authenticate' => 'Digest realm="myhost@testrealm.com"'
33
- })
61
+ })
34
62
  end
35
63
 
36
64
  it "should not set opaque" do
37
- authorization_header.should_not include(%Q(opaque=))
65
+ expect(authorization_header).not_to include("opaque=")
38
66
  end
39
67
  end
40
68
 
41
69
  context "with specified quality of protection (qop)" do
42
70
  before do
43
71
  @digest = setup_digest({
44
- 'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE", qop="auth"',
72
+ 'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE", qop="auth"'
45
73
  })
46
74
  end
47
75
 
48
76
  it "should set prefix" do
49
- authorization_header.should =~ /^Digest /
77
+ expect(authorization_header).to match(/^Digest /)
50
78
  end
51
79
 
52
80
  it "should set username" do
53
- authorization_header.should include(%Q(username="Mufasa"))
81
+ expect(authorization_header).to include('username="Mufasa"')
54
82
  end
55
83
 
56
84
  it "should set digest-uri" do
57
- authorization_header.should include(%Q(uri="/dir/index.html"))
85
+ expect(authorization_header).to include('uri="/dir/index.html"')
58
86
  end
59
87
 
60
88
  it "should set qop" do
61
- authorization_header.should include(%Q(qop="auth"))
89
+ expect(authorization_header).to include('qop="auth"')
62
90
  end
63
91
 
64
92
  it "should set cnonce" do
65
- authorization_header.should include(%Q(cnonce="md5(deadbeef)"))
93
+ expect(authorization_header).to include('cnonce="md5(deadbeef)"')
66
94
  end
67
95
 
68
96
  it "should set nonce-count" do
69
- authorization_header.should include(%Q(nc="00000001"))
97
+ expect(authorization_header).to include("nc=00000001")
70
98
  end
71
99
 
72
100
  it "should set response" do
73
101
  request_digest = "md5(md5(Mufasa:myhost@testrealm.com:Circle Of Life):NONCE:00000001:md5(deadbeef):auth:md5(GET:/dir/index.html))"
74
- authorization_header.should include(%Q(response="#{request_digest}"))
102
+ expect(authorization_header).to include(%(response="#{request_digest}"))
75
103
  end
76
104
  end
77
105
 
106
+ context "when quality of protection (qop) is unquoted" do
107
+ before do
108
+ @digest = setup_digest({
109
+ 'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE", qop=auth'
110
+ })
111
+ end
112
+
113
+ it "should still set qop" do
114
+ expect(authorization_header).to include('qop="auth"')
115
+ end
116
+ end
78
117
 
79
118
  context "with unspecified quality of protection (qop)" do
80
119
  before do
81
120
  @digest = setup_digest({
82
- 'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE"',
121
+ 'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE"'
83
122
  })
84
123
  end
85
124
 
86
125
  it "should set prefix" do
87
- authorization_header.should =~ /^Digest /
126
+ expect(authorization_header).to match(/^Digest /)
88
127
  end
89
128
 
90
129
  it "should set username" do
91
- authorization_header.should include(%Q(username="Mufasa"))
130
+ expect(authorization_header).to include('username="Mufasa"')
92
131
  end
93
132
 
94
133
  it "should set digest-uri" do
95
- authorization_header.should include(%Q(uri="/dir/index.html"))
134
+ expect(authorization_header).to include('uri="/dir/index.html"')
96
135
  end
97
136
 
98
137
  it "should not set qop" do
99
- authorization_header.should_not include(%Q(qop=))
138
+ expect(authorization_header).not_to include("qop=")
100
139
  end
101
140
 
102
141
  it "should not set cnonce" do
103
- authorization_header.should_not include(%Q(cnonce=))
142
+ expect(authorization_header).not_to include("cnonce=")
104
143
  end
105
144
 
106
145
  it "should not set nonce-count" do
107
- authorization_header.should_not include(%Q(nc=))
146
+ expect(authorization_header).not_to include("nc=")
108
147
  end
109
148
 
110
149
  it "should set response" do
111
150
  request_digest = "md5(md5(Mufasa:myhost@testrealm.com:Circle Of Life):NONCE:md5(GET:/dir/index.html))"
112
- authorization_header.should include(%Q(response="#{request_digest}"))
151
+ expect(authorization_header).to include(%(response="#{request_digest}"))
152
+ end
153
+ end
154
+
155
+ context "with http basic auth response when net digest auth expected" do
156
+ it "should not fail" do
157
+ @digest = setup_digest({
158
+ 'www-authenticate' => 'WWW-Authenticate: Basic realm="testrealm.com""'
159
+ })
160
+
161
+ expect(authorization_header).to include("Digest")
162
+ end
163
+ end
164
+
165
+ context "with multiple authenticate headers" do
166
+ before do
167
+ @digest = setup_digest({
168
+ 'www-authenticate' => 'NTLM, Digest realm="myhost@testrealm.com", nonce="NONCE", qop="auth"'
169
+ })
170
+ end
171
+
172
+ it "should set prefix" do
173
+ expect(authorization_header).to match(/^Digest /)
174
+ end
175
+
176
+ it "should set username" do
177
+ expect(authorization_header).to include('username="Mufasa"')
178
+ end
179
+
180
+ it "should set digest-uri" do
181
+ expect(authorization_header).to include('uri="/dir/index.html"')
182
+ end
183
+
184
+ it "should set qop" do
185
+ expect(authorization_header).to include('qop="auth"')
186
+ end
187
+
188
+ it "should set cnonce" do
189
+ expect(authorization_header).to include('cnonce="md5(deadbeef)"')
190
+ end
191
+
192
+ it "should set nonce-count" do
193
+ expect(authorization_header).to include("nc=00000001")
194
+ end
195
+
196
+ it "should set response" do
197
+ request_digest = "md5(md5(Mufasa:myhost@testrealm.com:Circle Of Life):NONCE:00000001:md5(deadbeef):auth:md5(GET:/dir/index.html))"
198
+ expect(authorization_header).to include(%(response="#{request_digest}"))
199
+ end
200
+ end
201
+
202
+ context "with algorithm specified" do
203
+ before do
204
+ @digest = setup_digest({
205
+ 'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE", qop="auth", algorithm=MD5'
206
+ })
207
+ end
208
+
209
+ it "should recognise algorithm was specified" do
210
+ expect( @digest.send :algorithm_present? ).to be(true)
211
+ end
212
+
213
+ it "should set the algorithm header" do
214
+ expect(authorization_header).to include('algorithm="MD5"')
215
+ end
216
+ end
217
+
218
+ context "with md5-sess algorithm specified" do
219
+ before do
220
+ @digest = setup_digest({
221
+ 'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE", qop="auth", algorithm=MD5-sess'
222
+ })
223
+ end
224
+
225
+ it "should recognise algorithm was specified" do
226
+ expect( @digest.send :algorithm_present? ).to be(true)
227
+ end
228
+
229
+ it "should set the algorithm header" do
230
+ expect(authorization_header).to include('algorithm="MD5-sess"')
231
+ end
232
+
233
+ it "should set response using md5-sess algorithm" do
234
+ request_digest = "md5(md5(md5(Mufasa:myhost@testrealm.com:Circle Of Life):NONCE:md5(deadbeef)):NONCE:00000001:md5(deadbeef):auth:md5(GET:/dir/index.html))"
235
+ expect(authorization_header).to include(%(response="#{request_digest}"))
113
236
  end
237
+
114
238
  end
239
+
115
240
  end