ethon 0.7.3 → 0.7.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MzIwZTI3ZDU0NzcyNGIwYTcyNDQwMzBhMTE3YWVjOTk4M2NmODg3Yg==
4
+ N2ZmZmIxYjlmYzhiMDJmODM5YjczNWE5NGQwYTA1OTIzMTU2YTQ5YQ==
5
5
  data.tar.gz: !binary |-
6
- ODA0NWYyYWJmMWJiZTExN2JlNmY4YmI4ZDM4YTEzOTkwNzNhODM5MA==
6
+ YThkNDc2ZmViYTdlZDkxNWUxMjRiNmE5NzIyNDUyN2QxMDlkNDc2MA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NTk5ZjIxNjQ4NDVmYTkzMGE2NDBjNTA2MTI5MzA3ODE4NjA2Mzg2MjkzNzk5
10
- NGNhMmEzNjBiODc3OGQ2OTZmNzUwNmI2ZTVmZjVjYjk2YjA5OThjYzM0MzA2
11
- YWE2OTBiODZiZGJjOTA3YjdjMWY5YTVmNGRjOTgwYTBjMDQwYjc=
9
+ ZjZjYTk3OGM3MGNlMmU3YmJiMGNkM2ZhMGE3MGRlNWUyYmYzMjFkOTRjNmVj
10
+ YWY1NzBmZTIyYTFlY2I2M2ZlMzhmMDk1ZWJiNDk2MDlhODJhMTg1ZWVhM2Yy
11
+ MjM5ODJjNWI0MTY3MWU0NzkxZTFkNWQ0YTdkZGJhMmY1YzdmYzc=
12
12
  data.tar.gz: !binary |-
13
- NTgzMzlkN2Q3YTY5YWIyMWRmNzdlMDFjZGFkZTdkOTYyNjZkMWI3ZTEyMGRi
14
- NTA2ODhhMjdjYmYwOTg2MDNlMjVlZmUzZWIzNGExODg1YzNmN2MwNGQ5ZGJi
15
- ZTIzNjllMmQzYzczMGI3MTIxYzA2NWViNmU4ZWI0MDJkMTU3ODg=
13
+ MmZiN2MxYmQyYmM4YWExOTIxYzU4NDlkYWRhYmE0M2RlZWIzOGJlY2IwOThm
14
+ MzkyZGQ0OGMzOTQyZWE0ZjZhODU5ZTlkMjk3ZWFjZGI2Y2E0NzZiOTM3ZjFl
15
+ NTkyMzYzNDQ2NWRjY2FkOWJjMDVjZGFkZmRmZDE3ZmI3ZjRmYTg=
@@ -2,7 +2,17 @@
2
2
 
3
3
  ## Master
4
4
 
5
- [Full Changelog](https://github.com/typhoeus/ethon/compare/v0.7.3...master)
5
+ [Full Changelog](https://github.com/typhoeus/ethon/compare/v0.7.4...master)
6
+
7
+ ## 0.7.4
8
+
9
+ [Full Changelog](https://github.com/typhoeus/ethon/compare/v0.7.3...v0.7.4)
10
+
11
+ * Support different array encodings for params.
12
+ ([Marcello Barnaba](https://github.com/ifad), [\#104](https://github.com/typhoeus/ethon/pull/104))
13
+ * Programtic access to version infos.
14
+ ([Jonas Wagner](https://github.com/jwagner), [\#90](https://github.com/typhoeus/ethon/pull/90))
15
+
6
16
 
7
17
  ## 0.7.3
8
18
 
@@ -10,6 +10,18 @@ module Ethon
10
10
  layout :code, :msg_code, :easy_handle, :pointer, :data, MsgData
11
11
  end
12
12
 
13
+ class VersionInfoData < ::FFI::Struct
14
+ layout :curl_version, :uint8,
15
+ :version, :string,
16
+ :version_num, :int,
17
+ :host, :string,
18
+ :features, :int,
19
+ :ssl_version, :string,
20
+ :ssl_version_num, :long,
21
+ :libz_version, :string,
22
+ :protocols, :pointer
23
+ end
24
+
13
25
  # :nodoc:
14
26
  class FDSet < ::FFI::Struct
15
27
  if Curl.windows?
@@ -39,5 +39,24 @@ module Ethon
39
39
 
40
40
  # :nodoc:
41
41
  MsgCode = enum(:msg_code, msg_codes)
42
+
43
+ VERSION_IPV6 = (1<<0) # IPv6-enabled
44
+ VERSION_KERBEROS4 = (1<<1) # kerberos auth is supported
45
+ VERSION_SSL = (1<<2) # SSL options are present
46
+ VERSION_LIBZ = (1<<3) # libz features are present
47
+ VERSION_NTLM = (1<<4) # NTLM auth is supported
48
+ VERSION_GSSNEGOTIATE = (1<<5) # Negotiate auth supp
49
+ VERSION_DEBUG = (1<<6) # built with debug capabilities
50
+ VERSION_ASYNCHDNS = (1<<7) # asynchronous dns resolves
51
+ VERSION_SPNEGO = (1<<8) # SPNEGO auth is supported
52
+ VERSION_LARGEFILE = (1<<9) # supports files bigger than 2GB
53
+ VERSION_IDN = (1<<10) # International Domain Names support
54
+ VERSION_SSPI = (1<<11) # SSPI is supported
55
+ VERSION_CONV = (1<<12) # character conversions supported
56
+ VERSION_CURLDEBUG = (1<<13) # debug memory tracking supported
57
+ VERSION_TLSAUTH_SRP = (1<<14) # TLS-SRP auth is supported
58
+ VERSION_NTLM_WB = (1<<15) # NTLM delegating to winbind helper
59
+ VERSION_HTTP2 = (1<<16) # HTTP2 support built
60
+ VERSION_GSSAPI = (1<<17) # GSS-API is supported
42
61
  end
43
62
  end
@@ -44,6 +44,8 @@ module Ethon
44
44
  base.attach_function :multi_setopt_off_t, :curl_multi_setopt, [:pointer, :multi_option, :int64], :multi_code
45
45
 
46
46
  base.attach_function :version, :curl_version, [], :string
47
+ base.attach_function :version_info, :curl_version_info, [], Curl::VersionInfoData.ptr
48
+
47
49
  base.attach_function :slist_append, :curl_slist_append, [:pointer, :string], :pointer
48
50
  base.attach_function :slist_free_all, :curl_slist_free_all, [:pointer], :void
49
51
  base.instance_variable_set(:@blocking, true)
@@ -1,4 +1,5 @@
1
1
  require 'ethon/easy/informations'
2
+ require 'ethon/easy/features'
2
3
  require 'ethon/easy/callbacks'
3
4
  require 'ethon/easy/options'
4
5
  require 'ethon/easy/header'
@@ -39,6 +40,7 @@ module Ethon
39
40
  include Ethon::Easy::Http
40
41
  include Ethon::Easy::Operations
41
42
  include Ethon::Easy::ResponseCallbacks
43
+ extend Ethon::Easy::Features
42
44
 
43
45
  # Returns the curl return code.
44
46
  #
@@ -0,0 +1,30 @@
1
+ module Ethon
2
+ class Easy
3
+
4
+ # This module contains class methods for feature checks
5
+ module Features
6
+ # Returns true if this curl version supports zlib.
7
+ #
8
+ # @example Return wether zlib is supported.
9
+ # Ethon::Easy.supports_zlib?
10
+ #
11
+ # @return [ Boolean ] True if supported, else false.
12
+ def supports_zlib?
13
+ !!(Curl.version_info[:features] & Curl::VERSION_LIBZ)
14
+ end
15
+
16
+ # Returns true if this curl version supports AsynchDNS.
17
+ #
18
+ # @example
19
+ # Ethon::Easy.supports_asynch_dns?
20
+ #
21
+ # @return [ Boolean ] True if supported, else false.
22
+ def supports_asynch_dns?
23
+ !!(Curl.version_info[:features] & Curl::VERSION_ASYNCHDNS)
24
+ end
25
+
26
+ alias :supports_timeout_ms? :supports_asynch_dns?
27
+
28
+ end
29
+ end
30
+ end
@@ -8,6 +8,8 @@ module Ethon
8
8
  # for more real actions like GET, HEAD, POST and PUT.
9
9
  module Actionable
10
10
 
11
+ QUERY_OPTIONS = [ :params, :body, :params_encoding ]
12
+
11
13
  # Create a new action.
12
14
  #
13
15
  # @example Create a new action.
@@ -19,7 +21,7 @@ module Ethon
19
21
  # @return [ Action ] A new action.
20
22
  def initialize(url, options)
21
23
  @url = url
22
- @options = options.dup
24
+ @options, @query_options = parse_options(options)
23
25
  end
24
26
 
25
27
  # Return the url.
@@ -42,6 +44,16 @@ module Ethon
42
44
  @options
43
45
  end
44
46
 
47
+ # Returns the query options hash.
48
+ #
49
+ # @example Return query options.
50
+ # action.query_options
51
+ #
52
+ # @return [ Hash ] The query options.
53
+ def query_options
54
+ @query_options
55
+ end
56
+
45
57
  # Return the params.
46
58
  #
47
59
  # @example Return params.
@@ -49,7 +61,7 @@ module Ethon
49
61
  #
50
62
  # @return [ Params ] The params.
51
63
  def params
52
- @params ||= Params.new(@easy, options.delete(:params))
64
+ @params ||= Params.new(@easy, query_options.fetch(:params, nil))
53
65
  end
54
66
 
55
67
  # Return the form.
@@ -59,7 +71,17 @@ module Ethon
59
71
  #
60
72
  # @return [ Form ] The form.
61
73
  def form
62
- @form ||= Form.new(@easy, options.delete(:body))
74
+ @form ||= Form.new(@easy, query_options.fetch(:body, nil))
75
+ end
76
+
77
+ # Get the requested array encoding. By default it's
78
+ # :typhoeus, but it can also be set to :rack.
79
+ #
80
+ # @example Get encoding from options
81
+ # action.params_encoding
82
+ #
83
+ def params_encoding
84
+ @params_encoding ||= query_options.fetch(:params_encoding, :typhoeus)
63
85
  end
64
86
 
65
87
  # Setup everything necessary for a proper request.
@@ -70,6 +92,7 @@ module Ethon
70
92
  # @param [ easy ] easy the easy to setup.
71
93
  def setup(easy)
72
94
  @easy = easy
95
+
73
96
  if params.empty?
74
97
  easy.url = url
75
98
  else
@@ -87,6 +110,8 @@ module Ethon
87
110
  # @param [ Easy ] easy The easy to setup.
88
111
  def set_params(easy)
89
112
  params.escape = true
113
+ params.params_encoding = params_encoding
114
+
90
115
  base_url, base_params = url.split("?")
91
116
  base_params += "&" if base_params
92
117
  easy.url = "#{base_url}?#{base_params}#{params.to_s}"
@@ -100,6 +125,21 @@ module Ethon
100
125
  # @param [ Easy ] easy The easy to setup.
101
126
  def set_form(easy)
102
127
  end
128
+
129
+ private
130
+
131
+ def parse_options(options)
132
+ query_options = {}
133
+ options = options.dup
134
+
135
+ QUERY_OPTIONS.each do |query_option|
136
+ if options.key?(query_option)
137
+ query_options[query_option] = options.delete(query_option)
138
+ end
139
+ end
140
+
141
+ return options, query_options
142
+ end
103
143
  end
104
144
  end
105
145
  end
@@ -14,6 +14,7 @@ module Ethon
14
14
  # @param [ Easy ] easy The easy to setup.
15
15
  def set_form(easy)
16
16
  easy.url ||= url
17
+ form.params_encoding = params_encoding
17
18
  if form.multipart?
18
19
  form.escape = false
19
20
  form.materialize
@@ -14,6 +14,7 @@ module Ethon
14
14
  def set_form(easy)
15
15
  easy.upload = true
16
16
  form.escape = true
17
+ form.params_encoding = params_encoding
17
18
  easy.infilesize = form.to_s.bytesize
18
19
  easy.set_read_callback(form.to_s)
19
20
  end
@@ -77,15 +77,18 @@ module Ethon
77
77
  eval %Q|def #{name}; Curl.send(:get_info_#{type}, :#{name}, handle); end|
78
78
  end
79
79
 
80
- # Returns this curl version supports zlib.
80
+ # Returns true if this curl version supports zlib.
81
81
  #
82
82
  # @example Return wether zlib is supported.
83
83
  # easy.supports_zlib?
84
84
  #
85
85
  # @return [ Boolean ] True if supported, else false.
86
+ # @deprecated Please use the static version instead
86
87
  def supports_zlib?
87
- !!(Curl.version.match(/zlib/))
88
+ Kernel.warn("Ethon: Easy#supports_zlib? is deprecated and will be removed, please use Easy#.")
89
+ Easy.supports_zlib?
88
90
  end
91
+
89
92
  end
90
93
  end
91
94
  end
@@ -8,6 +8,7 @@ module Ethon
8
8
  # :nodoc:
9
9
  def self.included(base)
10
10
  base.send(:attr_accessor, :escape)
11
+ base.send(:attr_accessor, :params_encoding)
11
12
  end
12
13
 
13
14
  # Return wether there are elements in params or not.
@@ -95,18 +96,37 @@ module Ethon
95
96
  def recursively_generate_pairs(h, prefix, pairs)
96
97
  case h
97
98
  when Hash
98
- h.each_pair do |k,v|
99
- key = prefix.nil? ? k : "#{prefix}[#{k}]"
100
- pairs_for(v, key, pairs)
101
- end
99
+ encode_hash_pairs(h, prefix, pairs)
102
100
  when Array
103
- h.each_with_index do |v, i|
104
- key = "#{prefix}[#{i}]"
105
- pairs_for(v, key, pairs)
101
+ if params_encoding == :rack
102
+ encode_rack_array_pairs(h, prefix, pairs)
103
+ else
104
+ encode_indexed_array_pairs(h, prefix, pairs)
106
105
  end
107
106
  end
108
107
  end
109
108
 
109
+ def encode_hash_pairs(h, prefix, pairs)
110
+ h.each_pair do |k,v|
111
+ key = prefix.nil? ? k : "#{prefix}[#{k}]"
112
+ pairs_for(v, key, pairs)
113
+ end
114
+ end
115
+
116
+ def encode_indexed_array_pairs(h, prefix, pairs)
117
+ h.each_with_index do |v, i|
118
+ key = "#{prefix}[#{i}]"
119
+ pairs_for(v, key, pairs)
120
+ end
121
+ end
122
+
123
+ def encode_rack_array_pairs(h, prefix, pairs)
124
+ h.each do |v|
125
+ key = "#{prefix}[]"
126
+ pairs_for(v, key, pairs)
127
+ end
128
+ end
129
+
110
130
  def pairs_for(v, key, pairs)
111
131
  case v
112
132
  when Hash, Array
@@ -1,5 +1,5 @@
1
1
  module Ethon
2
2
 
3
3
  # Ethon version.
4
- VERSION = '0.7.3'
4
+ VERSION = '0.7.4'
5
5
  end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ethon::Easy::Informations do
4
+
5
+ describe "#supports_asynch_dns?" do
6
+ it "returns boolean" do
7
+ expect([true, false].include? Ethon::Easy.supports_asynch_dns?).to be_truthy
8
+ end
9
+ end
10
+
11
+ describe "#supports_zlib?" do
12
+ it "returns boolean" do
13
+ expect([true, false].include? Ethon::Easy.supports_zlib?).to be_truthy
14
+ end
15
+ end
16
+
17
+ describe "#supports_timeout_ms?" do
18
+ it "returns boolean" do
19
+ expect([true, false].include? Ethon::Easy.supports_timeout_ms?).to be_truthy
20
+ end
21
+ end
22
+
23
+ end
@@ -5,7 +5,8 @@ describe Ethon::Easy::Http::Post do
5
5
  let(:url) { "http://localhost:3001/" }
6
6
  let(:params) { nil }
7
7
  let(:form) { nil }
8
- let(:post) { described_class.new(url, {:params => params, :body => form}) }
8
+ let(:options) { Hash.new }
9
+ let(:post) { described_class.new(url, options.merge({:params => params, :body => form})) }
9
10
 
10
11
  describe "#setup" do
11
12
  context "when nothing" do
@@ -39,6 +40,25 @@ describe Ethon::Easy::Http::Post do
39
40
  expect(easy.url).to eq("#{url}?a=1%26")
40
41
  end
41
42
 
43
+ context "with arrays" do
44
+ let(:params) { {:a => %w( foo bar )} }
45
+
46
+ context "by default" do
47
+ it "encodes them with indexes" do
48
+ post.setup(easy)
49
+ expect(easy.url).to eq("#{url}?a%5B0%5D=foo&a%5B1%5D=bar")
50
+ end
51
+ end
52
+
53
+ context "when params_encoding is :rack" do
54
+ let(:options) { {:params_encoding => :rack} }
55
+ it "encodes them without indexes" do
56
+ post.setup(easy)
57
+ expect(easy.url).to eq("#{url}?a%5B%5D=foo&a%5B%5D=bar")
58
+ end
59
+ end
60
+ end
61
+
42
62
  it "sets postfieldsize" do
43
63
  expect(easy).to receive(:postfieldsize=).with(0)
44
64
  post.setup(easy)
@@ -214,6 +234,26 @@ describe Ethon::Easy::Http::Post do
214
234
  end
215
235
  end
216
236
  end
237
+
238
+ context "when arrays" do
239
+ let(:form) { {:a => %w( foo bar )} }
240
+
241
+ context "by default" do
242
+ it "sets copypostfields with indexed, escaped representation" do
243
+ expect(easy).to receive(:copypostfields=).with('a%5B0%5D=foo&a%5B1%5D=bar')
244
+ post.setup(easy)
245
+ end
246
+ end
247
+
248
+ context "when params_encoding is :rack" do
249
+ let(:options) { {:params_encoding => :rack} }
250
+
251
+ it "sets copypostfields with non-indexed, escaped representation" do
252
+ expect(easy).to receive(:copypostfields=).with('a%5B%5D=foo&a%5B%5D=bar')
253
+ post.setup(easy)
254
+ end
255
+ end
256
+ end
217
257
  end
218
258
 
219
259
  context "when params and body" do
@@ -5,7 +5,8 @@ describe Ethon::Easy::Http::Put do
5
5
  let(:url) { "http://localhost:3001/" }
6
6
  let(:params) { nil }
7
7
  let(:form) { nil }
8
- let(:put) { described_class.new(url, {:params => params, :body => form}) }
8
+ let(:options) { Hash.new }
9
+ let(:put) { described_class.new(url, options.merge({:params => params, :body => form})) }
9
10
 
10
11
  describe "#setup" do
11
12
  context "when nothing" do
@@ -41,6 +42,25 @@ describe Ethon::Easy::Http::Put do
41
42
  expect(easy.url).to eq("#{url}?a=1%26")
42
43
  end
43
44
 
45
+ context "with arrays" do
46
+ let(:params) { {:a => %w( foo bar )} }
47
+
48
+ context "by default" do
49
+ it "encodes them with indexes" do
50
+ put.setup(easy)
51
+ expect(easy.url).to eq("#{url}?a%5B0%5D=foo&a%5B1%5D=bar")
52
+ end
53
+ end
54
+
55
+ context "when params_encoding is :rack" do
56
+ let(:options) { {:params_encoding => :rack} }
57
+ it "encodes them without indexes" do
58
+ put.setup(easy)
59
+ expect(easy.url).to eq("#{url}?a%5B%5D=foo&a%5B%5D=bar")
60
+ end
61
+ end
62
+ end
63
+
44
64
  it "sets upload" do
45
65
  expect(easy).to receive(:upload=).with(true)
46
66
  put.setup(easy)
@@ -117,6 +137,29 @@ describe Ethon::Easy::Http::Put do
117
137
  end
118
138
  end
119
139
  end
140
+
141
+ context "when arrays" do
142
+ let(:form) { {:a => %w( foo bar )} }
143
+
144
+ before do
145
+ put.setup(easy)
146
+ easy.perform
147
+ end
148
+
149
+ context "by default" do
150
+ it "submits an indexed, escaped representation" do
151
+ expect(easy.response_body).to include('"body":"a%5B0%5D=foo&a%5B1%5D=bar"')
152
+ end
153
+ end
154
+
155
+ context "when params_encoding is :rack" do
156
+ let(:options) { {:params_encoding => :rack} }
157
+
158
+ it "submits an non-indexed, escaped representation" do
159
+ expect(easy.response_body).to include('"body":"a%5B%5D=foo&a%5B%5D=bar"')
160
+ end
161
+ end
162
+ end
120
163
  end
121
164
 
122
165
  context "when params and body"
@@ -88,7 +88,10 @@ describe Ethon::Easy::Informations do
88
88
 
89
89
  describe "#supports_zlib?" do
90
90
  it "returns true" do
91
+ Kernel.should_receive(:warn) #deprecation warning
91
92
  expect(easy.supports_zlib?).to be_truthy
92
93
  end
93
94
  end
95
+
96
+
94
97
  end
@@ -104,9 +104,9 @@ describe Ethon::Easy::Options do
104
104
  end
105
105
  end
106
106
 
107
- if Ethon::Curl.version.match("c-ares")
107
+ if Ethon::Easy.supports_timeout_ms?
108
108
  context "when timeout_ms" do
109
- let(:timeout_ms) { 900 }
109
+ let(:timeout_ms) { 100 }
110
110
 
111
111
  context "when request takes longer" do
112
112
  let(:url) { "localhost:3001?delay=1" }
@@ -118,13 +118,14 @@ describe Ethon::Easy::Options do
118
118
  end
119
119
 
120
120
  context "when connecttimeout_ms" do
121
- let(:connecttimeout_ms) { 1 }
121
+ let(:connecttimeout_ms) { 100 }
122
122
 
123
123
  context "when cannot connect" do
124
124
  let(:url) { "localhost:3002" }
125
125
 
126
126
  it "times out" do
127
- expect(easy.return_code).to eq(:couldnt_connect)
127
+ # this can either lead to a timeout or couldnt connect depending on which happens first
128
+ expect([:couldnt_connect, :operation_timedout]).to include(easy.return_code)
128
129
  end
129
130
  end
130
131
  end
@@ -106,10 +106,21 @@ describe Ethon::Easy::Queryable do
106
106
  context "when params contains an array" do
107
107
  let(:hash) { {:a => 1, :b => [2, 3]} }
108
108
 
109
- it "transforms" do
110
- expect(pairs).to include([:a, 1])
111
- expect(pairs).to include(["b[0]", 2])
112
- expect(pairs).to include(["b[1]", 3])
109
+ context "by default" do
110
+ it "transforms" do
111
+ expect(pairs).to include([:a, 1])
112
+ expect(pairs).to include(["b[0]", 2])
113
+ expect(pairs).to include(["b[1]", 3])
114
+ end
115
+ end
116
+
117
+ context "when params_encoding is :rack" do
118
+ before { params.params_encoding = :rack }
119
+ it "transforms without indexes" do
120
+ expect(pairs).to include([:a, 1])
121
+ expect(pairs).to include(["b[]", 2])
122
+ expect(pairs).to include(["b[]", 3])
123
+ end
113
124
  end
114
125
  end
115
126
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ethon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.3
4
+ version: 0.7.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hans Hasselberg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-20 00:00:00.000000000 Z
11
+ date: 2015-06-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -55,6 +55,7 @@ files:
55
55
  - lib/ethon/easy.rb
56
56
  - lib/ethon/easy/callbacks.rb
57
57
  - lib/ethon/easy/debug_info.rb
58
+ - lib/ethon/easy/features.rb
58
59
  - lib/ethon/easy/form.rb
59
60
  - lib/ethon/easy/header.rb
60
61
  - lib/ethon/easy/http.rb
@@ -103,6 +104,7 @@ files:
103
104
  - spec/ethon/curl_spec.rb
104
105
  - spec/ethon/easy/callbacks_spec.rb
105
106
  - spec/ethon/easy/debug_info_spec.rb
107
+ - spec/ethon/easy/features_spec.rb
106
108
  - spec/ethon/easy/form_spec.rb
107
109
  - spec/ethon/easy/header_spec.rb
108
110
  - spec/ethon/easy/http/custom_spec.rb
@@ -159,6 +161,7 @@ test_files:
159
161
  - spec/ethon/curl_spec.rb
160
162
  - spec/ethon/easy/callbacks_spec.rb
161
163
  - spec/ethon/easy/debug_info_spec.rb
164
+ - spec/ethon/easy/features_spec.rb
162
165
  - spec/ethon/easy/form_spec.rb
163
166
  - spec/ethon/easy/header_spec.rb
164
167
  - spec/ethon/easy/http/custom_spec.rb