httparty 0.13.7 → 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} +220 -59
  7. data/Gemfile +8 -3
  8. data/README.md +8 -7
  9. data/bin/httparty +3 -1
  10. data/docs/README.md +171 -0
  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 +17 -6
  26. data/examples/twitter.rb +2 -2
  27. data/examples/whoismyrep.rb +1 -1
  28. data/httparty.gemspec +7 -5
  29. data/lib/httparty/connection_adapter.rb +86 -20
  30. data/lib/httparty/cookie_hash.rb +10 -8
  31. data/lib/httparty/decompressor.rb +92 -0
  32. data/lib/httparty/exceptions.rb +8 -2
  33. data/lib/httparty/hash_conversions.rb +30 -8
  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 +68 -23
  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 +23 -21
  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 +156 -106
  45. data/lib/httparty/response/headers.rb +23 -19
  46. data/lib/httparty/response.rb +92 -13
  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 +98 -34
  52. data/website/css/common.css +1 -1
  53. metadata +34 -113
  54. data/.travis.yml +0 -7
  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 -52
  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 -90
  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 -468
  86. data/spec/httparty/cookie_hash_spec.rb +0 -83
  87. data/spec/httparty/exception_spec.rb +0 -38
  88. data/spec/httparty/hash_conversions_spec.rb +0 -41
  89. data/spec/httparty/logger/apache_formatter_spec.rb +0 -41
  90. data/spec/httparty/logger/curl_formatter_spec.rb +0 -18
  91. data/spec/httparty/logger/logger_spec.rb +0 -38
  92. data/spec/httparty/net_digest_auth_spec.rb +0 -230
  93. data/spec/httparty/parser_spec.rb +0 -173
  94. data/spec/httparty/request_spec.rb +0 -1073
  95. data/spec/httparty/response_spec.rb +0 -241
  96. data/spec/httparty/ssl_spec.rb +0 -74
  97. data/spec/httparty_spec.rb +0 -850
  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,38 +0,0 @@
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,230 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
-
3
- RSpec.describe Net::HTTPHeader::DigestAuthenticator do
4
- def setup_digest(response)
5
- digest = Net::HTTPHeader::DigestAuthenticator.new("Mufasa",
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
- digest
10
- end
11
-
12
- def authorization_header
13
- @digest.authorization_header.join(", ")
14
- end
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
44
-
45
- context "with an opaque value in the response header" do
46
- before do
47
- @digest = setup_digest({
48
- 'www-authenticate' => 'Digest realm="myhost@testrealm.com", opaque="solid"'
49
- })
50
- end
51
-
52
- it "should set opaque" do
53
- expect(authorization_header).to include('opaque="solid"')
54
- end
55
- end
56
-
57
- context "without an opaque valid in the response header" do
58
- before do
59
- @digest = setup_digest({
60
- 'www-authenticate' => 'Digest realm="myhost@testrealm.com"'
61
- })
62
- end
63
-
64
- it "should not set opaque" do
65
- expect(authorization_header).not_to include("opaque=")
66
- end
67
- end
68
-
69
- context "with specified quality of protection (qop)" do
70
- before do
71
- @digest = setup_digest({
72
- 'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE", qop="auth"'
73
- })
74
- end
75
-
76
- it "should set prefix" do
77
- expect(authorization_header).to match(/^Digest /)
78
- end
79
-
80
- it "should set username" do
81
- expect(authorization_header).to include('username="Mufasa"')
82
- end
83
-
84
- it "should set digest-uri" do
85
- expect(authorization_header).to include('uri="/dir/index.html"')
86
- end
87
-
88
- it "should set qop" do
89
- expect(authorization_header).to include('qop="auth"')
90
- end
91
-
92
- it "should set cnonce" do
93
- expect(authorization_header).to include('cnonce="md5(deadbeef)"')
94
- end
95
-
96
- it "should set nonce-count" do
97
- expect(authorization_header).to include("nc=00000001")
98
- end
99
-
100
- it "should set response" do
101
- request_digest = "md5(md5(Mufasa:myhost@testrealm.com:Circle Of Life):NONCE:00000001:md5(deadbeef):auth:md5(GET:/dir/index.html))"
102
- expect(authorization_header).to include(%(response="#{request_digest}"))
103
- end
104
- end
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
117
-
118
- context "with unspecified quality of protection (qop)" do
119
- before do
120
- @digest = setup_digest({
121
- 'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE"'
122
- })
123
- end
124
-
125
- it "should set prefix" do
126
- expect(authorization_header).to match(/^Digest /)
127
- end
128
-
129
- it "should set username" do
130
- expect(authorization_header).to include('username="Mufasa"')
131
- end
132
-
133
- it "should set digest-uri" do
134
- expect(authorization_header).to include('uri="/dir/index.html"')
135
- end
136
-
137
- it "should not set qop" do
138
- expect(authorization_header).not_to include("qop=")
139
- end
140
-
141
- it "should not set cnonce" do
142
- expect(authorization_header).not_to include("cnonce=")
143
- end
144
-
145
- it "should not set nonce-count" do
146
- expect(authorization_header).not_to include("nc=")
147
- end
148
-
149
- it "should set response" do
150
- request_digest = "md5(md5(Mufasa:myhost@testrealm.com:Circle Of Life):NONCE:md5(GET:/dir/index.html))"
151
- expect(authorization_header).to include(%(response="#{request_digest}"))
152
- end
153
- end
154
-
155
- context "with multiple authenticate headers" do
156
- before do
157
- @digest = setup_digest({
158
- 'www-authenticate' => 'NTLM, Digest realm="myhost@testrealm.com", nonce="NONCE", qop="auth"'
159
- })
160
- end
161
-
162
- it "should set prefix" do
163
- expect(authorization_header).to match(/^Digest /)
164
- end
165
-
166
- it "should set username" do
167
- expect(authorization_header).to include('username="Mufasa"')
168
- end
169
-
170
- it "should set digest-uri" do
171
- expect(authorization_header).to include('uri="/dir/index.html"')
172
- end
173
-
174
- it "should set qop" do
175
- expect(authorization_header).to include('qop="auth"')
176
- end
177
-
178
- it "should set cnonce" do
179
- expect(authorization_header).to include('cnonce="md5(deadbeef)"')
180
- end
181
-
182
- it "should set nonce-count" do
183
- expect(authorization_header).to include("nc=00000001")
184
- end
185
-
186
- it "should set response" do
187
- request_digest = "md5(md5(Mufasa:myhost@testrealm.com:Circle Of Life):NONCE:00000001:md5(deadbeef):auth:md5(GET:/dir/index.html))"
188
- expect(authorization_header).to include(%(response="#{request_digest}"))
189
- end
190
- end
191
-
192
- context "with algorithm specified" do
193
- before do
194
- @digest = setup_digest({
195
- 'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE", qop="auth", algorithm=MD5'
196
- })
197
- end
198
-
199
- it "should recognise algorithm was specified" do
200
- expect( @digest.send :algorithm_present? ).to be(true)
201
- end
202
-
203
- it "should set the algorithm header" do
204
- expect(authorization_header).to include('algorithm="MD5"')
205
- end
206
- end
207
-
208
- context "with md5-sess algorithm specified" do
209
- before do
210
- @digest = setup_digest({
211
- 'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE", qop="auth", algorithm=MD5-sess'
212
- })
213
- end
214
-
215
- it "should recognise algorithm was specified" do
216
- expect( @digest.send :algorithm_present? ).to be(true)
217
- end
218
-
219
- it "should set the algorithm header" do
220
- expect(authorization_header).to include('algorithm="MD5-sess"')
221
- end
222
-
223
- it "should set response using md5-sess algorithm" do
224
- 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))"
225
- expect(authorization_header).to include(%(response="#{request_digest}"))
226
- end
227
-
228
- end
229
-
230
- end
@@ -1,173 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
-
3
- RSpec.describe HTTParty::Parser do
4
- describe ".SupportedFormats" do
5
- it "returns a hash" do
6
- expect(HTTParty::Parser::SupportedFormats).to be_instance_of(Hash)
7
- end
8
- end
9
-
10
- describe ".call" do
11
- it "generates an HTTParty::Parser instance with the given body and format" do
12
- expect(HTTParty::Parser).to receive(:new).with('body', :plain).and_return(double(parse: nil))
13
- HTTParty::Parser.call('body', :plain)
14
- end
15
-
16
- it "calls #parse on the parser" do
17
- parser = double('Parser')
18
- expect(parser).to receive(:parse)
19
- allow(HTTParty::Parser).to receive_messages(new: parser)
20
- parser = HTTParty::Parser.call('body', :plain)
21
- end
22
- end
23
-
24
- describe ".formats" do
25
- it "returns the SupportedFormats constant" do
26
- expect(HTTParty::Parser.formats).to eq(HTTParty::Parser::SupportedFormats)
27
- end
28
-
29
- it "returns the SupportedFormats constant for subclasses" do
30
- class MyParser < HTTParty::Parser
31
- SupportedFormats = {"application/atom+xml" => :atom}
32
- end
33
- expect(MyParser.formats).to eq({"application/atom+xml" => :atom})
34
- end
35
- end
36
-
37
- describe ".format_from_mimetype" do
38
- it "returns a symbol representing the format mimetype" do
39
- expect(HTTParty::Parser.format_from_mimetype("text/plain")).to eq(:plain)
40
- end
41
-
42
- it "returns nil when the mimetype is not supported" do
43
- expect(HTTParty::Parser.format_from_mimetype("application/atom+xml")).to be_nil
44
- end
45
- end
46
-
47
- describe ".supported_formats" do
48
- it "returns a unique set of supported formats represented by symbols" do
49
- expect(HTTParty::Parser.supported_formats).to eq(HTTParty::Parser::SupportedFormats.values.uniq)
50
- end
51
- end
52
-
53
- describe ".supports_format?" do
54
- it "returns true for a supported format" do
55
- allow(HTTParty::Parser).to receive_messages(supported_formats: [:json])
56
- expect(HTTParty::Parser.supports_format?(:json)).to be_truthy
57
- end
58
-
59
- it "returns false for an unsupported format" do
60
- allow(HTTParty::Parser).to receive_messages(supported_formats: [])
61
- expect(HTTParty::Parser.supports_format?(:json)).to be_falsey
62
- end
63
- end
64
-
65
- describe "#parse" do
66
- before do
67
- @parser = HTTParty::Parser.new('body', :json)
68
- end
69
-
70
- it "attempts to parse supported formats" do
71
- allow(@parser).to receive_messages(supports_format?: true)
72
- expect(@parser).to receive(:parse_supported_format)
73
- @parser.parse
74
- end
75
-
76
- it "returns the unparsed body when the format is unsupported" do
77
- allow(@parser).to receive_messages(supports_format?: false)
78
- expect(@parser.parse).to eq(@parser.body)
79
- end
80
-
81
- it "returns nil for an empty body" do
82
- allow(@parser).to receive_messages(body: '')
83
- expect(@parser.parse).to be_nil
84
- end
85
-
86
- it "returns nil for a nil body" do
87
- allow(@parser).to receive_messages(body: nil)
88
- expect(@parser.parse).to be_nil
89
- end
90
-
91
- it "returns nil for a 'null' body" do
92
- allow(@parser).to receive_messages(body: "null")
93
- expect(@parser.parse).to be_nil
94
- end
95
-
96
- it "returns nil for a body with spaces only" do
97
- allow(@parser).to receive_messages(body: " ")
98
- expect(@parser.parse).to be_nil
99
- end
100
-
101
- it "does not raise exceptions for bodies with invalid encodings" do
102
- allow(@parser).to receive_messages(body: "\x80")
103
- allow(@parser).to receive_messages(supports_format?: false)
104
- expect(@parser.parse).to_not be_nil
105
- end
106
- end
107
-
108
- describe "#supports_format?" do
109
- it "utilizes the class method to determine if the format is supported" do
110
- expect(HTTParty::Parser).to receive(:supports_format?).with(:json)
111
- parser = HTTParty::Parser.new('body', :json)
112
- parser.send(:supports_format?)
113
- end
114
- end
115
-
116
- describe "#parse_supported_format" do
117
- it "calls the parser for the given format" do
118
- parser = HTTParty::Parser.new('body', :json)
119
- expect(parser).to receive(:json)
120
- parser.send(:parse_supported_format)
121
- end
122
-
123
- context "when a parsing method does not exist for the given format" do
124
- it "raises an exception" do
125
- parser = HTTParty::Parser.new('body', :atom)
126
- expect do
127
- parser.send(:parse_supported_format)
128
- end.to raise_error(NotImplementedError, "HTTParty::Parser has not implemented a parsing method for the :atom format.")
129
- end
130
-
131
- it "raises a useful exception message for subclasses" do
132
- atom_parser = Class.new(HTTParty::Parser) do
133
- def self.name
134
- 'AtomParser'
135
- end
136
- end
137
- parser = atom_parser.new 'body', :atom
138
- expect do
139
- parser.send(:parse_supported_format)
140
- end.to raise_error(NotImplementedError, "AtomParser has not implemented a parsing method for the :atom format.")
141
- end
142
- end
143
- end
144
-
145
- context "parsers" do
146
- subject do
147
- HTTParty::Parser.new('body', nil)
148
- end
149
-
150
- it "parses xml with MultiXml" do
151
- expect(MultiXml).to receive(:parse).with('body')
152
- subject.send(:xml)
153
- end
154
-
155
- it "parses json with JSON" do
156
- expect(JSON).to receive(:parse).with('body', :quirks_mode => true, :allow_nan => true)
157
- subject.send(:json)
158
- end
159
-
160
- it "parses html by simply returning the body" do
161
- expect(subject.send(:html)).to eq('body')
162
- end
163
-
164
- it "parses plain text by simply returning the body" do
165
- expect(subject.send(:plain)).to eq('body')
166
- end
167
-
168
- it "parses csv with CSV" do
169
- expect(CSV).to receive(:parse).with('body')
170
- subject.send(:csv)
171
- end
172
- end
173
- end