Skip to content

Commit ccc76f1

Browse files
rgisigerrgisiger
authored andcommitted
Leverage existing URI::Generic and Net::HTTP code for proxy handling
Details: - Replaced custom use_proxy? method with URI::Generic.use_proxy? to use already existing functionality for handling the `no_proxy` string, which can include a list of comma- or space-separated elements. - Take advantage of the `p_no_proxy` variable in Net::HTTP to maintain environment variables related to proxy settings. - Note: With this change, wildcards are no longer usable to bypass the proxy due to limitations in the existing proxy code. Related to #5004
1 parent 4428c25 commit ccc76f1

File tree

6 files changed

+64
-40
lines changed

6 files changed

+64
-40
lines changed

rb/lib/selenium/webdriver/common/proxy.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
# specific language governing permissions and limitations
1818
# under the License.
1919

20+
# For more information on the proxy settings, see: https://www.w3.org/TR/webdriver2/#dfn-proxy-configuration
21+
2022
module Selenium
2123
module WebDriver
2224
class Proxy
@@ -89,7 +91,11 @@ def http=(value)
8991

9092
def no_proxy=(value)
9193
self.type = :manual
92-
@no_proxy = value
94+
@no_proxy = if value.is_a?(String)
95+
value.scan(/([^:,\s]+)(:\d+)?/).map(&:join) # adapted from URI::Generic.use_proxy?
96+
else
97+
value
98+
end
9399
end
94100

95101
def ssl=(value)
@@ -145,7 +151,7 @@ def as_json(*)
145151
'proxyType' => TYPES[type].downcase,
146152
'ftpProxy' => ftp,
147153
'httpProxy' => http,
148-
'noProxy' => no_proxy.is_a?(String) ? no_proxy.split(', ') : no_proxy,
154+
'noProxy' => no_proxy,
149155
'proxyAutoconfigUrl' => pac,
150156
'sslProxy' => ssl,
151157
'autodetect' => auto_detect,

rb/lib/selenium/webdriver/firefox/profile.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,8 @@ def proxy=(proxy)
138138
set_manual_proxy_preference 'ssl', proxy.ssl
139139
set_manual_proxy_preference 'socks', proxy.socks
140140

141-
self['network.proxy.no_proxies_on'] = proxy.no_proxy || ''
141+
# cf. http://kb.mozillazine.org/Network.proxy.no_proxies_on
142+
self['network.proxy.no_proxies_on'] = proxy.no_proxy&.join(',') || ''
142143
when :pac
143144
self['network.proxy.type'] = 2
144145
self['network.proxy.autoconfig_url'] = proxy.pac

rb/lib/selenium/webdriver/remote/http/default.rb

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
# KIND, either express or implied. See the License for the
1717
# specific language governing permissions and limitations
1818
# under the License.
19-
require 'ipaddr'
19+
require 'uri/generic'
2020

2121
module Selenium
2222
module WebDriver
@@ -88,7 +88,7 @@ def request(verb, url, headers, payload, redirects = 0)
8888
sleep 2
8989
retry
9090
rescue Errno::ECONNREFUSED => e
91-
raise e.class, "using proxy: #{proxy.http}" if use_proxy?
91+
raise e.class, "using proxy: #{http.proxy_uri}" if http.proxy?
9292

9393
raise
9494
end
@@ -119,18 +119,20 @@ def response_for(request)
119119
end
120120

121121
def new_http_client
122-
if use_proxy?
123-
url = @proxy.http
122+
if proxy
123+
url = proxy.http
124124
unless proxy.respond_to?(:http) && url
125125
raise Error::WebDriverError,
126-
"expected HTTP proxy, got #{@proxy.inspect}"
126+
"expected HTTP proxy, got #{proxy.inspect}"
127127
end
128128

129-
proxy = URI.parse(url)
129+
proxy_url = URI.parse(url)
130130

131-
Net::HTTP.new(server_url.host, server_url.port, proxy.host, proxy.port, proxy.user, proxy.password)
131+
Net::HTTP.new(server_url.host, server_url.port,
132+
proxy_url.host, proxy_url.port, proxy_url.user, proxy_url.password,
133+
proxy.no_proxy&.join(','))
132134
else
133-
Net::HTTP.new server_url.host, server_url.port
135+
Net::HTTP.new(server_url.host, server_url.port, nil)
134136
end
135137
end
136138

@@ -145,27 +147,6 @@ def proxy
145147
end
146148
end
147149
end
148-
149-
def use_proxy?
150-
return false if proxy.nil?
151-
152-
if proxy.no_proxy
153-
ignored = proxy.no_proxy.split(',').any? do |host|
154-
host == '*' ||
155-
host == server_url.host || (
156-
begin
157-
IPAddr.new(host).include?(server_url.host)
158-
rescue ArgumentError
159-
false
160-
end
161-
)
162-
end
163-
164-
!ignored
165-
else
166-
true
167-
end
168-
end
169150
end # Default
170151
end # Http
171152
end # Remote

rb/sig/lib/selenium/webdriver/remote/http/default.rbs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ module Selenium
3939
def new_http_client: () -> untyped
4040

4141
def proxy: () -> untyped
42-
43-
def use_proxy?: () -> untyped
4442
end
4543
end
4644
end

rb/spec/unit/selenium/webdriver/proxy_spec.rb

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ module WebDriver
2626
{
2727
ftp: 'mythicalftpproxy:21',
2828
http: 'mythicalproxy:80',
29-
no_proxy: 'noproxy',
29+
no_proxy: 'noproxy,noproxy2,noproxy3:443,127.0.0.1,127.0.0.1:80',
3030
ssl: 'mythicalsslproxy',
3131
socks: 'mythicalsocksproxy:65555',
3232
socks_username: 'test',
@@ -59,21 +59,27 @@ module WebDriver
5959

6060
expect(proxy.ftp).to eq(proxy_settings[:ftp])
6161
expect(proxy.http).to eq(proxy_settings[:http])
62-
expect(proxy.no_proxy).to eq(proxy_settings[:no_proxy])
62+
expect(proxy.no_proxy).to eq(%w[noproxy noproxy2 noproxy3:443 127.0.0.1 127.0.0.1:80])
6363
expect(proxy.ssl).to eq(proxy_settings[:ssl])
6464
expect(proxy.socks).to eq(proxy_settings[:socks])
6565
expect(proxy.socks_username).to eq(proxy_settings[:socks_username])
6666
expect(proxy.socks_password).to eq(proxy_settings[:socks_password])
6767
expect(proxy.socks_version).to eq(proxy_settings[:socks_version])
6868
end
6969

70+
it 'allows different kinds of separator for no_proxy string list', :aggregate_failures do
71+
proxy = described_class.new({no_proxy: 'noproxy,noproxy2, noproxy3:443 127.0.0.1 , 127.0.0.1:80'})
72+
73+
expect(proxy.no_proxy).to eq(%w[noproxy noproxy2 noproxy3:443 127.0.0.1 127.0.0.1:80])
74+
end
75+
7076
it 'returns a hash of the json properties to serialize', :aggregate_failures do
7177
proxy_json = described_class.new(proxy_settings).as_json
7278

7379
expect(proxy_json['proxyType']).to eq('manual')
7480
expect(proxy_json['ftpProxy']).to eq(proxy_settings[:ftp])
7581
expect(proxy_json['httpProxy']).to eq(proxy_settings[:http])
76-
expect(proxy_json['noProxy']).to eq([proxy_settings[:no_proxy]])
82+
expect(proxy_json['noProxy']).to eq(%w[noproxy noproxy2 noproxy3:443 127.0.0.1 127.0.0.1:80])
7783
expect(proxy_json['sslProxy']).to eq(proxy_settings[:ssl])
7884
expect(proxy_json['socksProxy']).to eq(proxy_settings[:socks])
7985
expect(proxy_json['socksUsername']).to eq(proxy_settings[:socks_username])
@@ -95,7 +101,7 @@ module WebDriver
95101
expect(proxy_json['autodetect']).to be true
96102
end
97103

98-
it 'onlies add settings that are not nil', :aggregate_failures do
104+
it 'only add settings that are not nil', :aggregate_failures do
99105
settings = {type: :manual, http: 'http proxy'}
100106

101107
proxy = described_class.new(settings)

rb/spec/unit/selenium/webdriver/remote/http/default_spec.rb

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ module Http
2626
describe Default do
2727
let(:client) do
2828
client = described_class.new
29-
client.server_url = URI.parse('http://example.com')
29+
client.server_url = URI.parse('http://test.example.com')
3030

3131
client
3232
end
@@ -60,7 +60,7 @@ module Http
6060
expect(http.proxy_user).to eq('foo')
6161
expect(http.proxy_pass).to eq('bar')
6262

63-
expect(http.address).to eq('example.com')
63+
expect(http.address).to eq('test.example.com')
6464
end
6565

6666
it 'raises an error if the proxy is not an HTTP proxy' do
@@ -96,6 +96,11 @@ module Http
9696
http = client.send :http
9797
expect(http).not_to be_proxy
9898
end
99+
100+
with_env('http_proxy' => 'proxy.org:8080', no_proxy_var => 'test.example.com') do
101+
http = client.send :http
102+
expect(http).not_to be_proxy
103+
end
99104
end
100105

101106
it "ignores the #{no_proxy_var} environment variable when not matching" do
@@ -106,6 +111,14 @@ module Http
106111
expect(http.proxy_address).to eq('proxy.org')
107112
expect(http.proxy_port).to eq(8080)
108113
end
114+
115+
with_env('http_proxy' => 'proxy.org:8080', no_proxy_var => 'ample.com') do
116+
http = client.send :http
117+
118+
expect(http).to be_proxy
119+
expect(http.proxy_address).to eq('proxy.org')
120+
expect(http.proxy_port).to eq(8080)
121+
end
109122
end
110123

111124
it "understands a comma separated list of domains in #{no_proxy_var}" do
@@ -115,6 +128,13 @@ module Http
115128
end
116129
end
117130

131+
it "understands a space separated list of domains in #{no_proxy_var}" do
132+
with_env('http_proxy' => 'proxy.org:8080', no_proxy_var => 'example.com foo.com') do
133+
http = client.send :http
134+
expect(http).not_to be_proxy
135+
end
136+
end
137+
118138
it "understands subnetting in #{no_proxy_var}" do
119139
with_env('http_proxy' => 'proxy.org:8080', no_proxy_var => 'localhost,127.0.0.0/8') do
120140
client.server_url = URI.parse('http://127.0.0.1:4444/wd/hub')
@@ -123,6 +143,18 @@ module Http
123143
expect(http).not_to be_proxy
124144
end
125145
end
146+
147+
it "uses the specified proxy if the wildcard character is used in #{no_proxy_var}" do
148+
with_env('http_proxy' => 'proxy.org:8080', no_proxy_var => '*') do
149+
http = client.send :http
150+
expect(http).to be_proxy
151+
end
152+
153+
with_env('http_proxy' => 'proxy.org:8080', no_proxy_var => '*.example.com') do
154+
http = client.send :http
155+
expect(http).to be_proxy
156+
end
157+
end
126158
end
127159

128160
it 'raises a sane error if a proxy is refusing connections' do

0 commit comments

Comments
 (0)