proxy_fetcher 0.10.2 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -1
  3. data/Gemfile +8 -5
  4. data/Rakefile +7 -3
  5. data/gemfiles/nokogiri.gemfile +8 -6
  6. data/gemfiles/oga.gemfile +8 -6
  7. data/lib/proxy_fetcher.rb +46 -35
  8. data/lib/proxy_fetcher/client/client.rb +10 -3
  9. data/lib/proxy_fetcher/client/request.rb +4 -4
  10. data/lib/proxy_fetcher/configuration.rb +24 -19
  11. data/lib/proxy_fetcher/document.rb +0 -9
  12. data/lib/proxy_fetcher/document/adapters.rb +1 -1
  13. data/lib/proxy_fetcher/document/adapters/abstract_adapter.rb +3 -12
  14. data/lib/proxy_fetcher/document/adapters/nokogiri_adapter.rb +1 -1
  15. data/lib/proxy_fetcher/document/adapters/oga_adapter.rb +1 -1
  16. data/lib/proxy_fetcher/document/node.rb +2 -2
  17. data/lib/proxy_fetcher/exceptions.rb +6 -6
  18. data/lib/proxy_fetcher/manager.rb +42 -9
  19. data/lib/proxy_fetcher/providers/base.rb +43 -22
  20. data/lib/proxy_fetcher/providers/free_proxy_list.rb +9 -10
  21. data/lib/proxy_fetcher/providers/free_proxy_list_socks.rb +58 -0
  22. data/lib/proxy_fetcher/providers/free_proxy_list_ssl.rb +7 -15
  23. data/lib/proxy_fetcher/providers/free_proxy_list_us.rb +54 -0
  24. data/lib/proxy_fetcher/providers/http_tunnel.rb +11 -19
  25. data/lib/proxy_fetcher/providers/mtpro.rb +43 -0
  26. data/lib/proxy_fetcher/providers/proxy_list.rb +8 -16
  27. data/lib/proxy_fetcher/providers/proxypedia.rb +48 -0
  28. data/lib/proxy_fetcher/providers/proxyscrape_http.rb +65 -0
  29. data/lib/proxy_fetcher/providers/proxyscrape_socks4.rb +65 -0
  30. data/lib/proxy_fetcher/providers/proxyscrape_socks5.rb +65 -0
  31. data/lib/proxy_fetcher/providers/xroxy.rb +9 -17
  32. data/lib/proxy_fetcher/proxy.rb +16 -4
  33. data/lib/proxy_fetcher/utils/http_client.rb +7 -12
  34. data/lib/proxy_fetcher/utils/proxy_list_validator.rb +3 -1
  35. data/lib/proxy_fetcher/utils/proxy_validator.rb +21 -9
  36. data/lib/proxy_fetcher/version.rb +3 -3
  37. data/proxy_fetcher.gemspec +21 -16
  38. data/spec/fixtures/proxies.txt +14 -0
  39. data/spec/proxy_fetcher/client/client_spec.rb +72 -57
  40. data/spec/proxy_fetcher/configuration_spec.rb +11 -11
  41. data/spec/proxy_fetcher/document/adapters_spec.rb +8 -8
  42. data/spec/proxy_fetcher/document/node_spec.rb +4 -4
  43. data/spec/proxy_fetcher/manager_spec.rb +18 -0
  44. data/spec/proxy_fetcher/providers/base_spec.rb +9 -9
  45. data/spec/proxy_fetcher/providers/multiple_providers_spec.rb +4 -4
  46. data/spec/proxy_fetcher/providers/proxy_classes_spec.rb +28 -0
  47. data/spec/proxy_fetcher/proxy_spec.rb +14 -14
  48. data/spec/proxy_fetcher/version_spec.rb +2 -0
  49. data/spec/spec_helper.rb +10 -10
  50. data/spec/support/manager_examples.rb +21 -21
  51. metadata +27 -17
  52. data/lib/proxy_fetcher/providers/gather_proxy.rb +0 -58
  53. data/spec/proxy_fetcher/providers/free_proxy_list_spec.rb +0 -13
  54. data/spec/proxy_fetcher/providers/free_proxy_list_ssl_spec.rb +0 -11
  55. data/spec/proxy_fetcher/providers/gather_proxy_spec.rb +0 -11
  56. data/spec/proxy_fetcher/providers/http_tunnel_spec.rb +0 -11
  57. data/spec/proxy_fetcher/providers/proxy_list_spec.rb +0 -11
  58. data/spec/proxy_fetcher/providers/xroxy_spec.rb +0 -11
@@ -70,22 +70,17 @@ module ProxyFetcher
70
70
  def fetch
71
71
  response = process_http_request
72
72
  response.body.to_s
73
- rescue StandardError => error
74
- ProxyFetcher.logger.warn("Failed to process request to #{url} (#{error.message})")
75
- ''
76
- end
77
-
78
- def fetch_with_headers
79
- process_http_request
80
- rescue StandardError => error
81
- ProxyFetcher.logger.warn("Failed to process request to #{url} (#{error.message})")
82
- HTTP::Response.new(version: '1.1', status: 500, body: '')
73
+ rescue StandardError => e
74
+ ProxyFetcher.config.logger.warn("Failed to process request to #{url} (#{e.message})")
75
+ ""
83
76
  end
84
77
 
85
78
  protected
86
79
 
87
80
  def process_http_request(http_method: method, http_params: params)
88
- raise ArgumentError, 'wrong http method name!' unless HTTP::Request::METHODS.include?(http_method)
81
+ unless HTTP::Request::METHODS.include?(http_method)
82
+ raise ArgumentError, "'#{http_method}' is a wrong HTTP method name!"
83
+ end
89
84
 
90
85
  http.public_send(
91
86
  http_method.to_sym, url,
@@ -101,7 +96,7 @@ module ProxyFetcher
101
96
  #
102
97
  def default_headers
103
98
  {
104
- 'User-Agent' => ProxyFetcher.config.user_agent
99
+ "User-Agent" => ProxyFetcher.config.user_agent
105
100
  }
106
101
  end
107
102
  end
@@ -34,7 +34,9 @@ module ProxyFetcher
34
34
  proxy = target_proxies_lock.synchronize { target_proxies.shift }
35
35
  break unless proxy
36
36
 
37
- connectable_proxies_lock.synchronize { connectable_proxies << proxy } if proxy.connectable?
37
+ if proxy.connectable?
38
+ connectable_proxies_lock.synchronize { connectable_proxies << proxy }
39
+ end
38
40
  end
39
41
  end
40
42
  end
@@ -6,31 +6,43 @@ module ProxyFetcher
6
6
  # URL to check if proxy can be used (aka connectable?).
7
7
  class ProxyValidator
8
8
  # Default URL that will be used to check if proxy can be used.
9
- URL_TO_CHECK = 'https://google.com'.freeze
9
+ URL_TO_CHECK = "https://google.com"
10
10
 
11
11
  # Short variant to validate proxy.
12
12
  #
13
- # @param proxy_addr [String] proxy address or IP
14
- # @param proxy_port [String, Integer] proxy port
13
+ # @param address [String] proxy address or IP
14
+ # @param port [String, Integer] proxy port
15
15
  #
16
16
  # @return [Boolean]
17
17
  # true if connection to the server using proxy established, otherwise false
18
18
  #
19
- def self.connectable?(proxy_addr, proxy_port)
20
- new(proxy_addr, proxy_port).connectable?
19
+ def self.connectable?(address, port)
20
+ new(address, port).connectable?
21
21
  end
22
22
 
23
23
  # Initialize new ProxyValidator instance
24
24
  #
25
- # @param proxy_addr [String] proxy address or IP
26
- # @param proxy_port [String, Integer] proxy port
25
+ # @param address [String] Proxy address or IP
26
+ # @param port [String, Integer] Proxy port
27
+ # @param options [Hash] proxy options
28
+ # @option username [String] Proxy authentication username
29
+ # @option password [String] Proxy authentication password
30
+ # @option headers [Hash] Proxy headers
27
31
  #
28
32
  # @return [ProxyValidator]
29
33
  #
30
- def initialize(proxy_addr, proxy_port)
34
+ def initialize(address, port, options: {})
31
35
  timeout = ProxyFetcher.config.proxy_validation_timeout
36
+ proxy = [address, port.to_i]
32
37
 
33
- @http = HTTP.follow.via(proxy_addr, proxy_port.to_i).timeout(connect: timeout, read: timeout)
38
+ if options[:username] && options[:password]
39
+ proxy << options[:username]
40
+ proxy << options[:password]
41
+ end
42
+
43
+ proxy << options[:headers].to_h if options[:headers]
44
+
45
+ @http = HTTP.follow.via(*proxy).timeout(connect: timeout, read: timeout)
34
46
  end
35
47
 
36
48
  # Checks if proxy is connectable (can be used to connect
@@ -13,11 +13,11 @@ module ProxyFetcher
13
13
  # Major version number
14
14
  MAJOR = 0
15
15
  # Minor version number
16
- MINOR = 10
16
+ MINOR = 15
17
17
  # Smallest version number
18
- TINY = 2
18
+ TINY = 0
19
19
 
20
20
  # Full version number
21
- STRING = [MAJOR, MINOR, TINY].compact.join('.')
21
+ STRING = [MAJOR, MINOR, TINY].compact.join(".")
22
22
  end
23
23
  end
@@ -1,25 +1,30 @@
1
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
1
+ # frozen_string_literal: true
2
2
 
3
- require 'proxy_fetcher/version'
3
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "lib"))
4
+
5
+ require "proxy_fetcher/version"
4
6
 
5
7
  Gem::Specification.new do |gem|
6
- gem.name = 'proxy_fetcher'
8
+ gem.name = "proxy_fetcher"
7
9
  gem.version = ProxyFetcher.gem_version
8
- gem.summary = 'Ruby gem for dealing with proxy lists from different providers'
9
- gem.description = 'This gem can help your Ruby application to make HTTP(S) requests ' \
10
- 'using proxies by fetching and validating proxy lists from the different providers.'
11
- gem.authors = ['Nikita Bulai']
12
- gem.email = 'bulajnikita@gmail.com'
13
- gem.require_paths = ['lib']
14
- gem.bindir = 'bin'
10
+ gem.summary = "Ruby gem for dealing with proxy lists from different providers"
11
+ gem.description = <<-TEXT.strip.gsub(/[\s\n]+/, " ")
12
+ This gem can help your Ruby application to make HTTP(S) requests
13
+ using proxies by fetching and validating proxy lists from
14
+ the different providers.
15
+ TEXT
16
+ gem.authors = ["Nikita Bulai"]
17
+ gem.email = "bulajnikita@gmail.com"
18
+ gem.require_paths = ["lib"]
19
+ gem.bindir = "bin"
15
20
  gem.files = `git ls-files`.split($RS) - %w[README.md .travis.yml .rubocop.yml]
16
21
  gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
17
- gem.homepage = 'http://github.com/nbulaj/proxy_fetcher'
18
- gem.license = 'MIT'
19
- gem.required_ruby_version = '>= 2.0.0'
22
+ gem.homepage = "http://github.com/nbulaj/proxy_fetcher"
23
+ gem.license = "MIT"
24
+ gem.required_ruby_version = ">= 2.3.0"
20
25
 
21
- gem.add_runtime_dependency 'http', '~> 3.0'
26
+ gem.add_runtime_dependency "http", ">= 3", "< 5"
22
27
 
23
- gem.add_development_dependency 'rake', '>= 12.0'
24
- gem.add_development_dependency 'rspec', '~> 3.5'
28
+ gem.add_development_dependency "rake", ">= 12.0"
29
+ gem.add_development_dependency "rspec", "~> 3.9"
25
30
  end
@@ -0,0 +1,14 @@
1
+ 139.162.59.9:3128
2
+ 176.62.187.158:56351
3
+ 144.217.22.142:8080
4
+ 176.55.108.21:3128
5
+ 157.225.214.251:3128
6
+ 202.51.49.52:48298
7
+ 104.244.75.26:8080
8
+ 163.172.28.20:80
9
+ 187.56.191.12:3128
10
+ 129.194.12.26:80
11
+ 178.128.39.39:8080
12
+ 181.30.28.15:8080
13
+ 51.181.96.185:8080
14
+ 148.134.10.13
@@ -1,19 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
- require 'json'
3
+ require "spec_helper"
4
+ require "json"
5
5
 
6
- require 'evil-proxy'
7
- require 'evil-proxy/async'
6
+ require "evil-proxy"
7
+ require "evil-proxy/async"
8
8
 
9
- xdescribe ProxyFetcher::Client do
9
+ describe ProxyFetcher::Client do
10
10
  before :all do
11
11
  ProxyFetcher.configure do |config|
12
12
  config.provider = :xroxy
13
13
  config.client_timeout = 5
14
+ config.logger = ProxyFetcher::NullLogger.new
14
15
  end
15
16
 
16
- @server = EvilProxy::MITMProxyServer.new Port: 3128, Quiet: true
17
+ quiet = ENV.key?("LOG_MITM") ? ENV["LOG_MITM"] == "false" : true
18
+
19
+ @server = EvilProxy::MITMProxyServer.new Port: 3128, Quiet: quiet
17
20
  @server.start
18
21
  end
19
22
 
@@ -21,121 +24,133 @@ xdescribe ProxyFetcher::Client do
21
24
  @server.shutdown
22
25
  end
23
26
 
27
+ let(:local_proxy) { ProxyFetcher::Proxy.new(addr: "127.0.0.1", port: 3128, type: "HTTP, HTTPS") }
28
+
24
29
  # Use local proxy server in order to avoid side effects, non-working proxies, etc
25
30
  before :each do
26
- proxy = ProxyFetcher::Proxy.new(addr: '127.0.0.1', port: 3128, type: 'HTTP, HTTPS')
27
- ProxyFetcher::Client::ProxiesRegistry.manager.instance_variable_set(:'@proxies', [proxy])
28
- allow_any_instance_of(ProxyFetcher::Providers::Base).to receive(:fetch_proxies!).and_return([proxy])
31
+ ProxyFetcher::Client::ProxiesRegistry.manager.instance_variable_set(:'@proxies', [local_proxy])
32
+ allow_any_instance_of(ProxyFetcher::Providers::Base).to receive(:fetch_proxies).and_return([local_proxy])
29
33
  end
30
34
 
31
- context 'GET request with the valid proxy' do
32
- it 'successfully returns page content for HTTP' do
33
- content = ProxyFetcher::Client.get('http://httpbin.org')
35
+ context "GET request with the valid proxy" do
36
+ it "successfully returns page content for HTTP" do
37
+ content = ProxyFetcher::Client.get("http://httpbin.org/get")
34
38
 
35
39
  expect(content).not_to be_empty
36
40
  end
37
41
 
38
- it 'successfully returns page content for HTTPS' do
39
- content = ProxyFetcher::Client.get('https://httpbin.org')
42
+ # TODO: oh this SSL / MITM proxies ....
43
+ xit "successfully returns page content for HTTPS" do
44
+ content = ProxyFetcher::Client.get("https://httpbin.org/get")
40
45
 
41
46
  expect(content).not_to be_empty
42
47
  end
43
48
 
44
- it 'successfully returns page content using custom proxy' do
45
- manager = ProxyFetcher::Manager.new
46
-
47
- proxy = manager.get! until proxy
48
- content = ProxyFetcher::Client.get('http://httpbin.org', options: { proxy: proxy })
49
+ it "successfully returns page content using custom proxy" do
50
+ content = ProxyFetcher::Client.get("http://httpbin.org/get", options: { proxy: local_proxy })
49
51
 
50
52
  expect(content).not_to be_empty
51
53
  end
52
54
  end
53
55
 
54
- context 'POST request with the valid proxy' do
55
- it 'successfully returns page content for HTTP' do
56
+ context "POST request with the valid proxy" do
57
+ it "successfully returns page content for HTTP" do
56
58
  headers = {
57
- 'X-Proxy-Fetcher-Version' => ProxyFetcher::VERSION::STRING
59
+ "X-Proxy-Fetcher-Version" => ProxyFetcher::VERSION::STRING
58
60
  }
59
- content = ProxyFetcher::Client.post('http://httpbin.org/post', { param: 'value' } , headers: headers)
61
+
62
+ content = ProxyFetcher::Client.post(
63
+ "http://httpbin.org/post",
64
+ { param: "value" },
65
+ headers: headers
66
+ )
60
67
 
61
68
  expect(content).not_to be_empty
62
69
 
63
70
  json = JSON.parse(content)
64
71
 
65
- expect(json['headers']['X-Proxy-Fetcher-Version']).to eq(ProxyFetcher::VERSION::STRING)
66
- expect(json['headers']['User-Agent']).to eq(ProxyFetcher.config.user_agent)
72
+ expect(json["headers"]["X-Proxy-Fetcher-Version"]).to eq(ProxyFetcher::VERSION::STRING)
73
+ expect(json["headers"]["User-Agent"]).to eq(ProxyFetcher.config.user_agent)
67
74
  end
68
75
  end
69
76
 
70
- context 'PUT request with the valid proxy' do
71
- it 'successfully returns page content for HTTP' do
72
- content = ProxyFetcher::Client.put('http://httpbin.org/put', 'param=PutValue')
77
+ # TODO: EvilProxy incompatible with latest Ruby/Webrick
78
+ # @see https://github.com/bbtfr/evil-proxy/issues/10
79
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.6")
80
+ context "PUT request with the valid proxy" do
81
+ it "successfully returns page content for HTTP" do
82
+ content = ProxyFetcher::Client.put("http://httpbin.org/put", "param=PutValue")
73
83
 
74
- expect(content).not_to be_empty
84
+ expect(content).not_to be_empty
75
85
 
76
- json = JSON.parse(content)
86
+ json = JSON.parse(content)
77
87
 
78
- expect(json['data']).to eq('param=PutValue')
88
+ expect(json["form"]["param"]).to eq("PutValue")
89
+ end
79
90
  end
80
- end
81
91
 
82
- context 'PATCH request with the valid proxy' do
83
- it 'successfully returns page content for HTTP' do
84
- content = ProxyFetcher::Client.patch('http://httpbin.org/patch', param: 'value')
92
+ context "PATCH request with the valid proxy" do
93
+ it "successfully returns page content for HTTP" do
94
+ content = ProxyFetcher::Client.patch("http://httpbin.org/patch", param: "value")
85
95
 
86
- expect(content).not_to be_empty
96
+ expect(content).not_to be_empty
87
97
 
88
- json = JSON.parse(content)
98
+ json = JSON.parse(content)
89
99
 
90
- expect(json['form']['param']).to eq('value')
100
+ expect(json["form"]["param"]).to eq("value")
101
+ end
91
102
  end
92
103
  end
93
104
 
94
- context 'DELETE request with the valid proxy' do
95
- it 'successfully returns page content for HTTP' do
96
- content = ProxyFetcher::Client.delete('http://httpbin.org/delete')
105
+ context "DELETE request with the valid proxy" do
106
+ it "successfully returns page content for HTTP" do
107
+ content = ProxyFetcher::Client.delete("http://httpbin.org/delete")
97
108
 
98
109
  expect(content).not_to be_empty
99
110
  end
100
111
  end
101
112
 
102
- context 'HEAD request with the valid proxy' do
103
- it 'successfully works' do
104
- content = ProxyFetcher::Client.head('http://httpbin.org')
113
+ context "HEAD request with the valid proxy" do
114
+ it "successfully works" do
115
+ content = ProxyFetcher::Client.head("http://httpbin.org")
105
116
 
106
117
  expect(content).to be_empty
107
118
  end
108
119
  end
109
120
 
110
- context 'retries' do
111
- it 'raises an error when reaches max retries limit' do
121
+ context "retries" do
122
+ it "raises an error when reaches max retries limit" do
112
123
  allow(ProxyFetcher::Client::Request).to receive(:execute).and_raise(StandardError)
113
124
 
114
- expect { ProxyFetcher::Client.get('http://httpbin.org') }.to raise_error(ProxyFetcher::Exceptions::MaximumRetriesReached)
125
+ expect { ProxyFetcher::Client.get("http://httpbin.org", options: { max_retries: 10 }) }
126
+ .to raise_error(ProxyFetcher::Exceptions::MaximumRetriesReached)
115
127
  end
116
128
 
117
- it 'raises an error when http request returns an error' do
129
+ xit "raises an error when http request returns an error" do
118
130
  allow_any_instance_of(HTTP::Client).to receive(:get).and_return(StandardError.new)
119
131
 
120
- expect { ProxyFetcher::Client.get('http://httpbin.org') }.to raise_error(ProxyFetcher::Exceptions::MaximumRetriesReached)
132
+ expect { ProxyFetcher::Client.get("http://httpbin.org") }
133
+ .to raise_error(ProxyFetcher::Exceptions::MaximumRetriesReached)
121
134
  end
122
135
 
123
- it 'refreshes proxy lists if no proxy found' do
124
- ProxyFetcher::Client::ProxiesRegistry.manager.instance_variable_set(:'@proxies', [])
136
+ it "refreshes proxy lists if no proxy found" do
137
+ allow(ProxyFetcher::Manager.new).to receive(:proxies).and_return([])
125
138
 
126
- expect { ProxyFetcher::Client.get('http://httpbin.org') }.not_to raise_error
139
+ expect { ProxyFetcher::Client.get("http://httpbin.org") }
140
+ .not_to raise_error
127
141
  end
128
142
  end
129
143
 
130
- context 'redirects' do
131
- it 'follows redirect when present' do
132
- content = ProxyFetcher::Client.get('http://httpbin.org/absolute-redirect/2')
144
+ xcontext "redirects" do
145
+ it "follows redirect when present" do
146
+ content = ProxyFetcher::Client.get("http://httpbin.org/absolute-redirect/2")
133
147
 
134
148
  expect(content).not_to be_empty
135
149
  end
136
150
 
137
- it 'raises an error when reaches max redirects limit' do
138
- expect { ProxyFetcher::Client.get('http://httpbin.org/absolute-redirect/11') }.to raise_error(ProxyFetcher::Exceptions::MaximumRedirectsReached)
151
+ it "raises an error when reaches max redirects limit" do
152
+ expect { ProxyFetcher::Client.get("http://httpbin.org/absolute-redirect/11") }
153
+ .to raise_error(ProxyFetcher::Exceptions::MaximumRedirectsReached)
139
154
  end
140
155
  end
141
156
  end
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
3
+ require "spec_helper"
4
4
 
5
5
  describe ProxyFetcher::Configuration do
6
6
  before { ProxyFetcher.config.reset! }
7
7
  after { ProxyFetcher.config.reset! }
8
8
 
9
- context 'custom HTTP client' do
10
- it 'successfully setups if class has all the required methods' do
9
+ context "custom HTTP client" do
10
+ it "successfully setups if class has all the required methods" do
11
11
  class MyHTTPClient
12
12
  def self.fetch(url)
13
13
  url
@@ -17,7 +17,7 @@ describe ProxyFetcher::Configuration do
17
17
  expect { ProxyFetcher.config.http_client = MyHTTPClient }.not_to raise_error
18
18
  end
19
19
 
20
- it 'failed on setup if required methods are missing' do
20
+ it "failed on setup if required methods are missing" do
21
21
  MyWrongHTTPClient = Class.new
22
22
 
23
23
  expect { ProxyFetcher.config.http_client = MyWrongHTTPClient }
@@ -25,8 +25,8 @@ describe ProxyFetcher::Configuration do
25
25
  end
26
26
  end
27
27
 
28
- context 'custom proxy validator' do
29
- it 'successfully setups if class has all the required methods' do
28
+ context "custom proxy validator" do
29
+ it "successfully setups if class has all the required methods" do
30
30
  class MyProxyValidator
31
31
  def self.connectable?(*)
32
32
  true
@@ -36,7 +36,7 @@ describe ProxyFetcher::Configuration do
36
36
  expect { ProxyFetcher.config.proxy_validator = MyProxyValidator }.not_to raise_error
37
37
  end
38
38
 
39
- it 'failed on setup if required methods are missing' do
39
+ it "failed on setup if required methods are missing" do
40
40
  MyWrongProxyValidator = Class.new
41
41
 
42
42
  expect { ProxyFetcher.config.proxy_validator = MyWrongProxyValidator }
@@ -44,8 +44,8 @@ describe ProxyFetcher::Configuration do
44
44
  end
45
45
  end
46
46
 
47
- context 'custom provider' do
48
- it 'fails on registration if provider class already registered' do
47
+ context "custom provider" do
48
+ it "fails on registration if provider class already registered" do
49
49
  expect { ProxyFetcher::Configuration.register_provider(:xroxy, Class.new) }
50
50
  .to raise_error(ProxyFetcher::Exceptions::RegisteredProvider)
51
51
  end
@@ -58,13 +58,13 @@ describe ProxyFetcher::Configuration do
58
58
  end
59
59
  end
60
60
 
61
- context 'custom HTML parsing adapter' do
61
+ context "custom HTML parsing adapter" do
62
62
  it "fails if adapter can't be installed" do
63
63
  old_adapter = ProxyFetcher.config.adapter.dup
64
64
 
65
65
  class CustomAdapter < ProxyFetcher::Document::AbstractAdapter
66
66
  def self.install_requirements!
67
- require 'not_existing_gem'
67
+ require "not_existing_gem"
68
68
  end
69
69
  end
70
70