rest-client 2.0.2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.mailmap +10 -0
  4. data/.rubocop +2 -0
  5. data/.rubocop-disables.yml +46 -44
  6. data/.rubocop.yml +5 -0
  7. data/.travis.yml +31 -17
  8. data/AUTHORS +8 -0
  9. data/README.md +126 -9
  10. data/Rakefile +12 -4
  11. data/history.md +53 -0
  12. data/lib/restclient.rb +0 -1
  13. data/lib/restclient/abstract_response.rb +28 -2
  14. data/lib/restclient/exceptions.rb +3 -3
  15. data/lib/restclient/payload.rb +29 -4
  16. data/lib/restclient/raw_response.rb +17 -6
  17. data/lib/restclient/request.rb +94 -67
  18. data/lib/restclient/resource.rb +16 -6
  19. data/lib/restclient/response.rb +14 -4
  20. data/lib/restclient/utils.rb +47 -8
  21. data/lib/restclient/version.rb +2 -2
  22. data/rest-client.gemspec +3 -2
  23. data/spec/ISS.jpg +0 -0
  24. data/spec/helpers.rb +37 -5
  25. data/spec/integration/capath_digicert/3513523f.0 +22 -0
  26. data/spec/integration/capath_digicert/399e7759.0 +22 -0
  27. data/spec/integration/capath_digicert/digicert.crt +20 -17
  28. data/spec/integration/certs/digicert.crt +20 -17
  29. data/spec/integration/httpbin_spec.rb +41 -0
  30. data/spec/integration/integration_spec.rb +0 -7
  31. data/spec/unit/abstract_response_spec.rb +7 -7
  32. data/spec/unit/payload_spec.rb +51 -19
  33. data/spec/unit/raw_response_spec.rb +6 -2
  34. data/spec/unit/request2_spec.rb +8 -8
  35. data/spec/unit/request_spec.rb +53 -65
  36. data/spec/unit/resource_spec.rb +7 -7
  37. data/spec/unit/response_spec.rb +33 -22
  38. data/spec/unit/restclient_spec.rb +3 -2
  39. data/spec/unit/utils_spec.rb +10 -10
  40. metadata +34 -13
  41. data/spec/integration/capath_digicert/244b5494.0 +0 -19
  42. data/spec/integration/capath_digicert/81b9768f.0 +0 -19
  43. data/spec/unit/master_shake.jpg +0 -0
@@ -51,7 +51,8 @@ module RestClient
51
51
  Request.execute(options.merge(
52
52
  :method => :get,
53
53
  :url => url,
54
- :headers => headers), &(block || @block))
54
+ :headers => headers,
55
+ :log => log), &(block || @block))
55
56
  end
56
57
 
57
58
  def head(additional_headers={}, &block)
@@ -59,7 +60,8 @@ module RestClient
59
60
  Request.execute(options.merge(
60
61
  :method => :head,
61
62
  :url => url,
62
- :headers => headers), &(block || @block))
63
+ :headers => headers,
64
+ :log => log), &(block || @block))
63
65
  end
64
66
 
65
67
  def post(payload, additional_headers={}, &block)
@@ -68,7 +70,8 @@ module RestClient
68
70
  :method => :post,
69
71
  :url => url,
70
72
  :payload => payload,
71
- :headers => headers), &(block || @block))
73
+ :headers => headers,
74
+ :log => log), &(block || @block))
72
75
  end
73
76
 
74
77
  def put(payload, additional_headers={}, &block)
@@ -77,7 +80,8 @@ module RestClient
77
80
  :method => :put,
78
81
  :url => url,
79
82
  :payload => payload,
80
- :headers => headers), &(block || @block))
83
+ :headers => headers,
84
+ :log => log), &(block || @block))
81
85
  end
82
86
 
83
87
  def patch(payload, additional_headers={}, &block)
@@ -86,7 +90,8 @@ module RestClient
86
90
  :method => :patch,
87
91
  :url => url,
88
92
  :payload => payload,
89
- :headers => headers), &(block || @block))
93
+ :headers => headers,
94
+ :log => log), &(block || @block))
90
95
  end
91
96
 
92
97
  def delete(additional_headers={}, &block)
@@ -94,7 +99,8 @@ module RestClient
94
99
  Request.execute(options.merge(
95
100
  :method => :delete,
96
101
  :url => url,
97
- :headers => headers), &(block || @block))
102
+ :headers => headers,
103
+ :log => log), &(block || @block))
98
104
  end
99
105
 
100
106
  def to_s
@@ -121,6 +127,10 @@ module RestClient
121
127
  options[:open_timeout]
122
128
  end
123
129
 
130
+ def log
131
+ options[:log] || RestClient.log
132
+ end
133
+
124
134
  # Construct a subresource, preserving authentication.
125
135
  #
126
136
  # Example:
@@ -38,15 +38,25 @@ module RestClient
38
38
  "<RestClient::Response #{code.inspect} #{body_truncated(10).inspect}>"
39
39
  end
40
40
 
41
- def self.create(body, net_http_res, request)
41
+ # Initialize a Response object. Because RestClient::Response is
42
+ # (unfortunately) a subclass of String for historical reasons,
43
+ # Response.create is the preferred initializer.
44
+ #
45
+ # @param [String, nil] body The response body from the Net::HTTPResponse
46
+ # @param [Net::HTTPResponse] net_http_res
47
+ # @param [RestClient::Request] request
48
+ # @param [Time] start_time
49
+ def self.create(body, net_http_res, request, start_time=nil)
42
50
  result = self.new(body || '')
43
51
 
44
- result.response_set_vars(net_http_res, request)
52
+ result.response_set_vars(net_http_res, request, start_time)
45
53
  fix_encoding(result)
46
54
 
47
55
  result
48
56
  end
49
57
 
58
+ # Set the String encoding according to the 'Content-Type: charset' header,
59
+ # if possible.
50
60
  def self.fix_encoding(response)
51
61
  charset = RestClient::Utils.get_encoding_from_headers(response.headers)
52
62
  encoding = nil
@@ -54,8 +64,8 @@ module RestClient
54
64
  begin
55
65
  encoding = Encoding.find(charset) if charset
56
66
  rescue ArgumentError
57
- if RestClient.log
58
- RestClient.log << "No such encoding: #{charset.inspect}"
67
+ if response.log
68
+ response.log << "No such encoding: #{charset.inspect}"
59
69
  end
60
70
  end
61
71
 
@@ -1,3 +1,5 @@
1
+ require 'http/accept'
2
+
1
3
  module RestClient
2
4
  # Various utility methods
3
5
  module Utils
@@ -13,8 +15,8 @@ module RestClient
13
15
  #
14
16
  # @param headers [Hash<Symbol,String>]
15
17
  #
16
- # @return [String, nil] encoding Return the string encoding or nil if no
17
- # header is found.
18
+ # @return [String, nil] Return the string encoding or nil if no header is
19
+ # found.
18
20
  #
19
21
  # @example
20
22
  # >> get_encoding_from_headers({:content_type => 'text/plain; charset=UTF-8'})
@@ -24,19 +26,52 @@ module RestClient
24
26
  type_header = headers[:content_type]
25
27
  return nil unless type_header
26
28
 
27
- _content_type, params = cgi_parse_header(type_header)
29
+ # TODO: remove this hack once we drop support for Ruby 2.0
30
+ if RUBY_VERSION.start_with?('2.0')
31
+ _content_type, params = deprecated_cgi_parse_header(type_header)
32
+
33
+ if params.include?('charset')
34
+ return params.fetch('charset').gsub(/(\A["']*)|(["']*\z)/, '')
35
+ end
36
+
37
+ else
28
38
 
29
- if params.include?('charset')
30
- return params.fetch('charset').gsub(/(\A["']*)|(["']*\z)/, '')
39
+ begin
40
+ _content_type, params = cgi_parse_header(type_header)
41
+ rescue HTTP::Accept::ParseError
42
+ return nil
43
+ else
44
+ params['charset']
45
+ end
31
46
  end
47
+ end
32
48
 
33
- nil
49
+ # Parse a Content-Type like header.
50
+ #
51
+ # Return the main content-type and a hash of params.
52
+ #
53
+ # @param [String] line
54
+ # @return [Array(String, Hash)]
55
+ #
56
+ def self.cgi_parse_header(line)
57
+ types = HTTP::Accept::MediaTypes.parse(line)
58
+
59
+ if types.empty?
60
+ raise HTTP::Accept::ParseError.new("Found no types in header line")
61
+ end
62
+
63
+ [types.first.mime_type, types.first.parameters]
34
64
  end
35
65
 
36
66
  # Parse semi-colon separated, potentially quoted header string iteratively.
37
67
  #
38
68
  # @private
39
69
  #
70
+ # @deprecated This method is deprecated and only exists to support Ruby
71
+ # 2.0, which is not supported by HTTP::Accept.
72
+ #
73
+ # @todo remove this method when dropping support for Ruby 2.0
74
+ #
40
75
  def self._cgi_parseparam(s)
41
76
  return enum_for(__method__, s) unless block_given?
42
77
 
@@ -66,11 +101,15 @@ module RestClient
66
101
  # probably doesn't read or perform particularly well in ruby.
67
102
  # https://github.com/python/cpython/blob/3.4/Lib/cgi.py#L301-L331
68
103
  #
69
- #
70
104
  # @param [String] line
71
105
  # @return [Array(String, Hash)]
72
106
  #
73
- def self.cgi_parse_header(line)
107
+ # @deprecated This method is deprecated and only exists to support Ruby
108
+ # 2.0, which is not supported by HTTP::Accept.
109
+ #
110
+ # @todo remove this method when dropping support for Ruby 2.0
111
+ #
112
+ def self.deprecated_cgi_parse_header(line)
74
113
  parts = _cgi_parseparam(';' + line)
75
114
  key = parts.next
76
115
  pdict = {}
@@ -1,6 +1,6 @@
1
1
  module RestClient
2
- VERSION_INFO = [2, 0, 2] unless defined?(self::VERSION_INFO)
3
- VERSION = VERSION_INFO.map(&:to_s).join('.') unless defined?(self::VERSION)
2
+ VERSION_INFO = [2, 1, 0].freeze
3
+ VERSION = VERSION_INFO.map(&:to_s).join('.').freeze
4
4
 
5
5
  def self.version
6
6
  VERSION
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
8
8
  s.authors = ['REST Client Team']
9
9
  s.description = 'A simple HTTP and REST client for Ruby, inspired by the Sinatra microframework style of specifying actions: get, put, post, delete.'
10
10
  s.license = 'MIT'
11
- s.email = 'rest.client@librelist.com'
11
+ s.email = 'discuss@rest-client.groups.io'
12
12
  s.executables = ['restclient']
13
13
  s.extra_rdoc_files = ['README.md', 'history.md']
14
14
  s.files = `git ls-files -z`.split("\0")
@@ -21,8 +21,9 @@ Gem::Specification.new do |s|
21
21
  s.add_development_dependency('pry', '~> 0')
22
22
  s.add_development_dependency('pry-doc', '~> 0')
23
23
  s.add_development_dependency('rdoc', '>= 2.4.2', '< 6.0')
24
- s.add_development_dependency('rubocop', '~> 0')
24
+ s.add_development_dependency('rubocop', '~> 0.49')
25
25
 
26
+ s.add_dependency('http-accept', '>= 1.7.0', '< 2.0')
26
27
  s.add_dependency('http-cookie', '>= 1.0.2', '< 2.0')
27
28
  s.add_dependency('mime-types', '>= 1.16', '< 4.0')
28
29
  s.add_dependency('netrc', '~> 0.8')
Binary file
@@ -1,10 +1,36 @@
1
1
  require 'uri'
2
2
 
3
3
  module Helpers
4
- def response_double(opts={})
5
- double('response', {:to_hash => {}}.merge(opts))
4
+
5
+ # @param [Hash] opts A hash of methods, passed directly to the double
6
+ # definition. Use this to stub other required methods.
7
+ #
8
+ # @return double for Net::HTTPResponse
9
+ def res_double(opts={})
10
+ instance_double('Net::HTTPResponse', {to_hash: {}, body: 'response body'}.merge(opts))
11
+ end
12
+
13
+ # Given a Net::HTTPResponse or double and a Request or double, create a
14
+ # RestClient::Response object.
15
+ #
16
+ # @param net_http_res_double an rspec double for Net::HTTPResponse
17
+ # @param request A RestClient::Request or rspec double
18
+ #
19
+ # @return [RestClient::Response]
20
+ #
21
+ def response_from_res_double(net_http_res_double, request=nil, duration: 1)
22
+ request ||= request_double()
23
+ start_time = Time.now - duration
24
+
25
+ response = RestClient::Response.create(net_http_res_double.body, net_http_res_double, request, start_time)
26
+
27
+ # mock duration to ensure it gets the value we expect
28
+ allow(response).to receive(:duration).and_return(duration)
29
+
30
+ response
6
31
  end
7
32
 
33
+ # Redirect stderr to a string for the duration of the passed block.
8
34
  def fake_stderr
9
35
  original_stderr = $stderr
10
36
  $stderr = StringIO.new
@@ -14,9 +40,15 @@ module Helpers
14
40
  $stderr = original_stderr
15
41
  end
16
42
 
43
+ # Create a double for RestClient::Request
17
44
  def request_double(url: 'http://example.com', method: 'get')
18
- double('request', url: url, uri: URI.parse(url), method: method,
19
- user: nil, password: nil, cookie_jar: HTTP::CookieJar.new,
20
- redirection_history: nil, args: {url: url, method: method})
45
+ instance_double('RestClient::Request',
46
+ url: url, uri: URI.parse(url), method: method, user: nil, password: nil,
47
+ cookie_jar: HTTP::CookieJar.new, redirection_history: nil,
48
+ args: {url: url, method: method})
49
+ end
50
+
51
+ def test_image_path
52
+ File.dirname(__FILE__) + "/ISS.jpg"
21
53
  end
22
54
  end
@@ -0,0 +1,22 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
3
+ MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
4
+ d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
5
+ QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
6
+ MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
7
+ b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
8
+ 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
9
+ CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
10
+ nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
11
+ 43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
12
+ T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
13
+ gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
14
+ BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
15
+ TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
16
+ DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
17
+ hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
18
+ 06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
19
+ PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
20
+ YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
21
+ CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
22
+ -----END CERTIFICATE-----
@@ -0,0 +1,22 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
3
+ MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
4
+ d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
5
+ QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
6
+ MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
7
+ b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
8
+ 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
9
+ CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
10
+ nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
11
+ 43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
12
+ T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
13
+ gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
14
+ BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
15
+ TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
16
+ DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
17
+ hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
18
+ 06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
19
+ PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
20
+ YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
21
+ CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
22
+ -----END CERTIFICATE-----
@@ -1,19 +1,22 @@
1
1
  -----BEGIN CERTIFICATE-----
2
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB
13
- Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY
14
- 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
- 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
- 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
- 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
- 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
19
22
  -----END CERTIFICATE-----
@@ -1,19 +1,22 @@
1
1
  -----BEGIN CERTIFICATE-----
2
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
19
22
  -----END CERTIFICATE-----
@@ -1,6 +1,8 @@
1
1
  require_relative '_lib'
2
2
  require 'json'
3
3
 
4
+ require 'zlib'
5
+
4
6
  describe RestClient::Request do
5
7
  before(:all) do
6
8
  WebMock.disable!
@@ -83,5 +85,44 @@ describe RestClient::Request do
83
85
  expect(ex.http_code).to eq 401
84
86
  }
85
87
  end
88
+
89
+ it 'handles gzipped/deflated responses' do
90
+ [['gzip', 'gzipped'], ['deflate', 'deflated']].each do |encoding, var|
91
+ raw = execute_httpbin(encoding, method: :get)
92
+
93
+ begin
94
+ data = JSON.parse(raw)
95
+ rescue StandardError
96
+ puts "Failed to parse: " + raw.inspect
97
+ raise
98
+ end
99
+
100
+ expect(data['method']).to eq 'GET'
101
+ expect(data.fetch(var)).to be true
102
+ end
103
+ end
104
+
105
+ it 'does not uncompress response when accept-encoding is set' do
106
+ # == gzip ==
107
+ raw = execute_httpbin('gzip', method: :get, headers: {accept_encoding: 'gzip, deflate'})
108
+
109
+ # check for gzip magic number
110
+ expect(raw.body).to start_with("\x1F\x8B".b)
111
+
112
+ decoded = Zlib::GzipReader.new(StringIO.new(raw.body)).read
113
+ parsed = JSON.parse(decoded)
114
+
115
+ expect(parsed['method']).to eq 'GET'
116
+ expect(parsed.fetch('gzipped')).to be true
117
+
118
+ # == delate ==
119
+ raw = execute_httpbin('deflate', method: :get, headers: {accept_encoding: 'gzip, deflate'})
120
+
121
+ decoded = Zlib::Inflate.new.inflate(raw.body)
122
+ parsed = JSON.parse(decoded)
123
+
124
+ expect(parsed['method']).to eq 'GET'
125
+ expect(parsed.fetch('deflated')).to be true
126
+ end
86
127
  end
87
128
  end