httparty 0.16.4 → 0.17.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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/Changelog.md +6 -0
- data/Gemfile +4 -0
- data/docs/README.md +2 -2
- data/examples/README.md +3 -0
- data/examples/peer_cert.rb +9 -0
- data/lib/httparty.rb +29 -9
- data/lib/httparty/connection_adapter.rb +28 -9
- data/lib/httparty/request.rb +14 -71
- data/lib/httparty/response.rb +4 -0
- data/lib/httparty/{fragment_with_response.rb → response_fragment.rb} +4 -5
- data/lib/httparty/text_encoder.rb +70 -0
- data/lib/httparty/version.rb +1 -1
- data/spec/fixtures/ssl/generate.sh +3 -3
- data/spec/fixtures/ssl/generated/bogushost.crt +27 -11
- data/spec/fixtures/ssl/generated/ca.crt +29 -14
- data/spec/fixtures/ssl/generated/ca.key +52 -15
- data/spec/fixtures/ssl/generated/selfsigned.crt +27 -12
- data/spec/fixtures/ssl/generated/server.crt +28 -11
- data/spec/fixtures/ssl/generated/server.key +52 -15
- data/spec/httparty/connection_adapter_spec.rb +128 -2
- data/spec/httparty/request_spec.rb +57 -35
- data/spec/httparty/{fragment_with_response_spec.rb → response_fragment_spec.rb} +6 -3
- data/spec/httparty/response_spec.rb +7 -1
- data/spec/httparty/ssl_spec.rb +10 -2
- data/spec/httparty_spec.rb +20 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/ssl_test_helper.rb +4 -4
- data/spec/support/stub_response.rb +1 -0
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e555084c3fc85098b7da66339a47958b2383014
|
4
|
+
data.tar.gz: 937364fd6bd11140590f15beb4b324fa89eef30c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f0a8e29081a7c99e7ebebbe885e717326cbd45930ed096c88d953c7ef0a53e16eec6cdf6f273eaa6dd83e1a2eb42c861e7917c81e267e3085cc709e42fa4506
|
7
|
+
data.tar.gz: 1fcbb78cf1e3b7ede28e10f8de4ac40f34da5d1ec241dbfac9ff432e12f859ffd50457e469c39c3d4351f0a9997e916a1e09cb322fbe363b5e6df1e4ef7284f0
|
data/.travis.yml
CHANGED
data/Changelog.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## 0.17.0
|
2
|
+
|
3
|
+
* [Fix encoding of streamed chunk](https://github.com/jnunemaker/httparty/pull/644)
|
4
|
+
* [Avoid modifying frozen strings](https://github.com/jnunemaker/httparty/pull/649)
|
5
|
+
* [Expose .connection on fragment block param](https://github.com/jnunemaker/httparty/pull/648)
|
6
|
+
* [Add support for `Net::HTTP#write_timeout` method (Ruby 2.6.0)](https://github.com/jnunemaker/httparty/pull/647)
|
1
7
|
|
2
8
|
## 0.16.4
|
3
9
|
* [Add support for Ruby 2.6](https://github.com/jnunemaker/httparty/pull/636)
|
data/Gemfile
CHANGED
data/docs/README.md
CHANGED
@@ -9,7 +9,7 @@ Makes http fun again!
|
|
9
9
|
## Parsing JSON
|
10
10
|
If the response Content Type is `application/json`, HTTParty will parse the response and return Ruby objects such as a hash or array. The default behavior for parsing JSON will return keys as strings. This can be supressed with the `format` option. To get hash keys as symbols:
|
11
11
|
|
12
|
-
```
|
12
|
+
```ruby
|
13
13
|
response = HTTParty.get('http://example.com', format: :plain)
|
14
14
|
JSON.parse response, symbolize_names: true
|
15
15
|
```
|
@@ -103,4 +103,4 @@ class Client
|
|
103
103
|
# get("resources", verify_peer: false)
|
104
104
|
end
|
105
105
|
end
|
106
|
-
```
|
106
|
+
```
|
data/examples/README.md
CHANGED
@@ -0,0 +1,9 @@
|
|
1
|
+
dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
require File.join(dir, 'httparty')
|
3
|
+
|
4
|
+
peer_cert = nil
|
5
|
+
HTTParty.get("https://www.example.com") do |fragment|
|
6
|
+
peer_cert ||= fragment.connection.peer_cert
|
7
|
+
end
|
8
|
+
|
9
|
+
puts "The server's certificate expires #{peer_cert.not_after}"
|
data/lib/httparty.rb
CHANGED
@@ -14,6 +14,9 @@ require 'httparty/net_digest_auth'
|
|
14
14
|
require 'httparty/version'
|
15
15
|
require 'httparty/connection_adapter'
|
16
16
|
require 'httparty/logger/logger'
|
17
|
+
require 'httparty/request/body'
|
18
|
+
require 'httparty/response_fragment'
|
19
|
+
require 'httparty/text_encoder'
|
17
20
|
|
18
21
|
# @see HTTParty::ClassMethods
|
19
22
|
module HTTParty
|
@@ -170,9 +173,9 @@ module HTTParty
|
|
170
173
|
# include HTTParty
|
171
174
|
# default_timeout 10
|
172
175
|
# end
|
173
|
-
def default_timeout(
|
174
|
-
|
175
|
-
default_options[:timeout] =
|
176
|
+
def default_timeout(value)
|
177
|
+
validate_timeout_argument(__method__, value)
|
178
|
+
default_options[:timeout] = value
|
176
179
|
end
|
177
180
|
|
178
181
|
# Allows setting a default open_timeout for all HTTP calls in seconds
|
@@ -181,9 +184,9 @@ module HTTParty
|
|
181
184
|
# include HTTParty
|
182
185
|
# open_timeout 10
|
183
186
|
# end
|
184
|
-
def open_timeout(
|
185
|
-
|
186
|
-
default_options[:open_timeout] =
|
187
|
+
def open_timeout(value)
|
188
|
+
validate_timeout_argument(__method__, value)
|
189
|
+
default_options[:open_timeout] = value
|
187
190
|
end
|
188
191
|
|
189
192
|
# Allows setting a default read_timeout for all HTTP calls in seconds
|
@@ -192,11 +195,24 @@ module HTTParty
|
|
192
195
|
# include HTTParty
|
193
196
|
# read_timeout 10
|
194
197
|
# end
|
195
|
-
def read_timeout(
|
196
|
-
|
197
|
-
default_options[:read_timeout] =
|
198
|
+
def read_timeout(value)
|
199
|
+
validate_timeout_argument(__method__, value)
|
200
|
+
default_options[:read_timeout] = value
|
198
201
|
end
|
199
202
|
|
203
|
+
# Allows setting a default write_timeout for all HTTP calls in seconds
|
204
|
+
# Supported by Ruby > 2.6.0
|
205
|
+
#
|
206
|
+
# class Foo
|
207
|
+
# include HTTParty
|
208
|
+
# write_timeout 10
|
209
|
+
# end
|
210
|
+
def write_timeout(value)
|
211
|
+
validate_timeout_argument(__method__, value)
|
212
|
+
default_options[:write_timeout] = value
|
213
|
+
end
|
214
|
+
|
215
|
+
|
200
216
|
# Set an output stream for debugging, defaults to $stderr.
|
201
217
|
# The output stream is passed on to Net::HTTP#set_debug_output.
|
202
218
|
#
|
@@ -560,6 +576,10 @@ module HTTParty
|
|
560
576
|
|
561
577
|
private
|
562
578
|
|
579
|
+
def validate_timeout_argument(timeout_type, value)
|
580
|
+
raise ArgumentError, "#{ timeout_type } must be an integer or float" unless value && (value.is_a?(Integer) || value.is_a?(Float))
|
581
|
+
end
|
582
|
+
|
563
583
|
def ensure_method_maintained_across_redirects(options)
|
564
584
|
unless options.key?(:maintain_method_across_redirects)
|
565
585
|
options[:maintain_method_across_redirects] = true
|
@@ -42,6 +42,7 @@ module HTTParty
|
|
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
|
+
# * :+write_timeout+: http connection write_timeout in seconds, overrides timeout if set (Ruby >= 2.6.0 required)
|
45
46
|
# * :+debug_output+: see HTTParty::ClassMethods.debug_output.
|
46
47
|
# * :+cert_store+: contains certificate data. see method 'attach_ssl_certificates'
|
47
48
|
# * :+pem+: contains pem client certificate data. see method 'attach_ssl_certificates'
|
@@ -113,19 +114,29 @@ module HTTParty
|
|
113
114
|
|
114
115
|
attach_ssl_certificates(http, options)
|
115
116
|
|
116
|
-
if
|
117
|
+
if add_timeout?(options[:timeout])
|
117
118
|
http.open_timeout = options[:timeout]
|
118
119
|
http.read_timeout = options[:timeout]
|
120
|
+
|
121
|
+
from_ruby_version('2.6.0', option: :write_timeout, warn: false) do
|
122
|
+
http.write_timeout = options[:timeout]
|
123
|
+
end
|
119
124
|
end
|
120
125
|
|
121
|
-
if
|
126
|
+
if add_timeout?(options[:read_timeout])
|
122
127
|
http.read_timeout = options[:read_timeout]
|
123
128
|
end
|
124
129
|
|
125
|
-
if
|
130
|
+
if add_timeout?(options[:open_timeout])
|
126
131
|
http.open_timeout = options[:open_timeout]
|
127
132
|
end
|
128
133
|
|
134
|
+
if add_timeout?(options[:write_timeout])
|
135
|
+
from_ruby_version('2.6.0', option: :write_timeout) do
|
136
|
+
http.write_timeout = options[:write_timeout]
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
129
140
|
if options[:debug_output]
|
130
141
|
http.set_debug_output(options[:debug_output])
|
131
142
|
end
|
@@ -138,18 +149,14 @@ module HTTParty
|
|
138
149
|
#
|
139
150
|
# @see https://bugs.ruby-lang.org/issues/6617
|
140
151
|
if options[:local_host]
|
141
|
-
|
152
|
+
from_ruby_version('2.0.0', option: :local_host) do
|
142
153
|
http.local_host = options[:local_host]
|
143
|
-
else
|
144
|
-
Kernel.warn("Warning: option :local_host requires Ruby version 2.0 or later")
|
145
154
|
end
|
146
155
|
end
|
147
156
|
|
148
157
|
if options[:local_port]
|
149
|
-
|
158
|
+
from_ruby_version('2.0.0', option: :local_port) do
|
150
159
|
http.local_port = options[:local_port]
|
151
|
-
else
|
152
|
-
Kernel.warn("Warning: option :local_port requires Ruby version 2.0 or later")
|
153
160
|
end
|
154
161
|
end
|
155
162
|
|
@@ -158,6 +165,18 @@ module HTTParty
|
|
158
165
|
|
159
166
|
private
|
160
167
|
|
168
|
+
def from_ruby_version(ruby_version, option: nil, warn: true)
|
169
|
+
if RUBY_VERSION >= ruby_version
|
170
|
+
yield
|
171
|
+
elsif warn
|
172
|
+
Kernel.warn("Warning: option #{ option } requires Ruby version #{ ruby_version } or later")
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def add_timeout?(timeout)
|
177
|
+
timeout && (timeout.is_a?(Integer) || timeout.is_a?(Float))
|
178
|
+
end
|
179
|
+
|
161
180
|
def clean_host(host)
|
162
181
|
strip_ipv6_brackets(host)
|
163
182
|
end
|
data/lib/httparty/request.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
1
|
require 'erb'
|
2
|
-
require 'httparty/request/body'
|
3
|
-
require 'httparty/fragment_with_response'
|
4
2
|
|
5
3
|
module HTTParty
|
6
4
|
class Request #:nodoc:
|
@@ -142,21 +140,22 @@ module HTTParty
|
|
142
140
|
validate
|
143
141
|
setup_raw_request
|
144
142
|
chunked_body = nil
|
143
|
+
current_http = http
|
145
144
|
|
146
|
-
self.last_response =
|
145
|
+
self.last_response = current_http.request(@raw_request) do |http_response|
|
147
146
|
if block
|
148
147
|
chunks = []
|
149
148
|
|
150
149
|
http_response.read_body do |fragment|
|
151
|
-
|
152
|
-
|
150
|
+
encoded_fragment = encode_text(fragment, http_response['content-type'])
|
151
|
+
chunks << encoded_fragment if !options[:stream_body]
|
152
|
+
block.call ResponseFragment.new(encoded_fragment, http_response, current_http)
|
153
153
|
end
|
154
154
|
|
155
155
|
chunked_body = chunks.join
|
156
156
|
end
|
157
157
|
end
|
158
158
|
|
159
|
-
|
160
159
|
handle_host_redirection if response_redirects?
|
161
160
|
result = handle_unauthorized
|
162
161
|
result ||= handle_response(chunked_body, &block)
|
@@ -273,74 +272,10 @@ module HTTParty
|
|
273
272
|
query_string_parts.size > 0 ? query_string_parts.join('&') : nil
|
274
273
|
end
|
275
274
|
|
276
|
-
def get_charset
|
277
|
-
content_type = last_response["content-type"]
|
278
|
-
if content_type.nil?
|
279
|
-
return nil
|
280
|
-
end
|
281
|
-
|
282
|
-
if content_type =~ /;\s*charset\s*=\s*([^=,;"\s]+)/i
|
283
|
-
return $1
|
284
|
-
end
|
285
|
-
|
286
|
-
if content_type =~ /;\s*charset\s*=\s*"((\\.|[^\\"])+)"/i
|
287
|
-
return $1.gsub(/\\(.)/, '\1')
|
288
|
-
end
|
289
|
-
|
290
|
-
nil
|
291
|
-
end
|
292
|
-
|
293
|
-
def encode_with_ruby_encoding(body, charset)
|
294
|
-
# NOTE: This will raise an argument error if the
|
295
|
-
# charset does not exist
|
296
|
-
encoding = Encoding.find(charset)
|
297
|
-
body.force_encoding(encoding.to_s)
|
298
|
-
rescue ArgumentError
|
299
|
-
body
|
300
|
-
end
|
301
|
-
|
302
275
|
def assume_utf16_is_big_endian
|
303
276
|
options[:assume_utf16_is_big_endian]
|
304
277
|
end
|
305
278
|
|
306
|
-
def encode_utf_16(body)
|
307
|
-
if body.bytesize >= 2
|
308
|
-
if body.getbyte(0) == 0xFF && body.getbyte(1) == 0xFE
|
309
|
-
return body.force_encoding("UTF-16LE")
|
310
|
-
elsif body.getbyte(0) == 0xFE && body.getbyte(1) == 0xFF
|
311
|
-
return body.force_encoding("UTF-16BE")
|
312
|
-
end
|
313
|
-
end
|
314
|
-
|
315
|
-
if assume_utf16_is_big_endian
|
316
|
-
body.force_encoding("UTF-16BE")
|
317
|
-
else
|
318
|
-
body.force_encoding("UTF-16LE")
|
319
|
-
end
|
320
|
-
end
|
321
|
-
|
322
|
-
def _encode_body(body)
|
323
|
-
charset = get_charset
|
324
|
-
|
325
|
-
if charset.nil?
|
326
|
-
return body
|
327
|
-
end
|
328
|
-
|
329
|
-
if "utf-16".casecmp(charset) == 0
|
330
|
-
encode_utf_16(body)
|
331
|
-
else
|
332
|
-
encode_with_ruby_encoding(body, charset)
|
333
|
-
end
|
334
|
-
end
|
335
|
-
|
336
|
-
def encode_body(body)
|
337
|
-
if "".respond_to?(:encoding)
|
338
|
-
_encode_body(body)
|
339
|
-
else
|
340
|
-
body
|
341
|
-
end
|
342
|
-
end
|
343
|
-
|
344
279
|
def handle_response(body, &block)
|
345
280
|
if response_redirects?
|
346
281
|
options[:limit] -= 1
|
@@ -363,7 +298,7 @@ module HTTParty
|
|
363
298
|
perform(&block)
|
364
299
|
else
|
365
300
|
body ||= last_response.body
|
366
|
-
body = body.nil? ? body :
|
301
|
+
body = body.nil? ? body : encode_text(body, last_response['content-type'])
|
367
302
|
Response.new(self, last_response, lambda { parse_response(body) }, body: body)
|
368
303
|
end
|
369
304
|
end
|
@@ -439,5 +374,13 @@ module HTTParty
|
|
439
374
|
@credentials_sent = true
|
440
375
|
end
|
441
376
|
end
|
377
|
+
|
378
|
+
def encode_text(text, content_type)
|
379
|
+
TextEncoder.new(
|
380
|
+
text,
|
381
|
+
content_type: content_type,
|
382
|
+
assume_utf16_is_big_endian: assume_utf16_is_big_endian
|
383
|
+
).call
|
384
|
+
end
|
442
385
|
end
|
443
386
|
end
|
data/lib/httparty/response.rb
CHANGED
@@ -2,18 +2,17 @@ require 'delegate'
|
|
2
2
|
|
3
3
|
module HTTParty
|
4
4
|
# Allow access to http_response and code by delegation on fragment
|
5
|
-
class
|
6
|
-
|
7
|
-
|
8
|
-
attr_reader :http_response
|
5
|
+
class ResponseFragment < SimpleDelegator
|
6
|
+
attr_reader :http_response, :connection
|
9
7
|
|
10
8
|
def code
|
11
9
|
@http_response.code.to_i
|
12
10
|
end
|
13
11
|
|
14
|
-
def initialize(fragment, http_response)
|
12
|
+
def initialize(fragment, http_response, connection)
|
15
13
|
@fragment = fragment
|
16
14
|
@http_response = http_response
|
15
|
+
@connection = connection
|
17
16
|
super fragment
|
18
17
|
end
|
19
18
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module HTTParty
|
2
|
+
class TextEncoder
|
3
|
+
attr_reader :text, :content_type, :assume_utf16_is_big_endian
|
4
|
+
|
5
|
+
def initialize(text, assume_utf16_is_big_endian: true, content_type: nil)
|
6
|
+
@text = text.dup
|
7
|
+
@content_type = content_type
|
8
|
+
@assume_utf16_is_big_endian = assume_utf16_is_big_endian
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
if can_encode?
|
13
|
+
encoded_text
|
14
|
+
else
|
15
|
+
text
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def can_encode?
|
22
|
+
''.respond_to?(:encoding) && charset
|
23
|
+
end
|
24
|
+
|
25
|
+
def encoded_text
|
26
|
+
if 'utf-16'.casecmp(charset) == 0
|
27
|
+
encode_utf_16
|
28
|
+
else
|
29
|
+
encode_with_ruby_encoding
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def encode_utf_16
|
34
|
+
if text.bytesize >= 2
|
35
|
+
if text.getbyte(0) == 0xFF && text.getbyte(1) == 0xFE
|
36
|
+
return text.force_encoding("UTF-16LE")
|
37
|
+
elsif text.getbyte(0) == 0xFE && text.getbyte(1) == 0xFF
|
38
|
+
return text.force_encoding("UTF-16BE")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
if assume_utf16_is_big_endian # option
|
43
|
+
text.force_encoding("UTF-16BE")
|
44
|
+
else
|
45
|
+
text.force_encoding("UTF-16LE")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def encode_with_ruby_encoding
|
50
|
+
# NOTE: This will raise an argument error if the
|
51
|
+
# charset does not exist
|
52
|
+
encoding = Encoding.find(charset)
|
53
|
+
text.force_encoding(encoding.to_s)
|
54
|
+
rescue ArgumentError
|
55
|
+
text
|
56
|
+
end
|
57
|
+
|
58
|
+
def charset
|
59
|
+
return nil if content_type.nil?
|
60
|
+
|
61
|
+
if (matchdata = content_type.match(/;\s*charset\s*=\s*([^=,;"\s]+)/i))
|
62
|
+
return matchdata.captures.first
|
63
|
+
end
|
64
|
+
|
65
|
+
if (matchdata = content_type.match(/;\s*charset\s*=\s*"((\\.|[^\\"])+)"/i))
|
66
|
+
return matchdata.captures.first.gsub(/\\(.)/, '\1')
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|