ferrum 0.12 → 0.13

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.
data/lib/ferrum/proxy.rb CHANGED
@@ -18,7 +18,6 @@ module Ferrum
18
18
  @port = port
19
19
  @user = user
20
20
  @password = password
21
- at_exit { stop }
22
21
  end
23
22
 
24
23
  def start
@@ -39,8 +38,10 @@ module Ferrum
39
38
  options.merge!(ProxyAuthProc: authenticator.method(:authenticate).to_proc)
40
39
  end
41
40
 
42
- @server = WEBrick::HTTPProxyServer.new(**options)
41
+ @server = HTTPProxyServer.new(**options)
43
42
  @server.start
43
+ at_exit { stop }
44
+
44
45
  @port = @server.config[:Port]
45
46
  end
46
47
 
@@ -54,5 +55,93 @@ module Ferrum
54
55
  @file&.unlink
55
56
  @server.shutdown
56
57
  end
58
+
59
+ # Fix hanging proxy at exit
60
+ class HTTPProxyServer < WEBrick::HTTPProxyServer
61
+ # rubocop:disable all
62
+ def do_CONNECT(req, res)
63
+ # Proxy Authentication
64
+ proxy_auth(req, res)
65
+
66
+ ua = Thread.current[:WEBrickSocket] # User-Agent
67
+ raise WEBrick::HTTPStatus::InternalServerError,
68
+ "[BUG] cannot get socket" unless ua
69
+
70
+ host, port = req.unparsed_uri.split(":", 2)
71
+ # Proxy authentication for upstream proxy server
72
+ if proxy = proxy_uri(req, res)
73
+ proxy_request_line = "CONNECT #{host}:#{port} HTTP/1.0"
74
+ if proxy.userinfo
75
+ credentials = "Basic " + [proxy.userinfo].pack("m0")
76
+ end
77
+ host, port = proxy.host, proxy.port
78
+ end
79
+
80
+ begin
81
+ @logger.debug("CONNECT: upstream proxy is `#{host}:#{port}'.")
82
+ os = TCPSocket.new(host, port) # origin server
83
+
84
+ if proxy
85
+ @logger.debug("CONNECT: sending a Request-Line")
86
+ os << proxy_request_line << CRLF
87
+ @logger.debug("CONNECT: > #{proxy_request_line}")
88
+ if credentials
89
+ @logger.debug("CONNECT: sending credentials")
90
+ os << "Proxy-Authorization: " << credentials << CRLF
91
+ end
92
+ os << CRLF
93
+ proxy_status_line = os.gets(LF)
94
+ @logger.debug("CONNECT: read Status-Line from the upstream server")
95
+ @logger.debug("CONNECT: < #{proxy_status_line}")
96
+ if %r{^HTTP/\d+\.\d+\s+200\s*} =~ proxy_status_line
97
+ while line = os.gets(LF)
98
+ break if /\A(#{CRLF}|#{LF})\z/om =~ line
99
+ end
100
+ else
101
+ raise WEBrick::HTTPStatus::BadGateway
102
+ end
103
+ end
104
+ @logger.debug("CONNECT #{host}:#{port}: succeeded")
105
+ res.status = WEBrick::HTTPStatus::RC_OK
106
+ rescue => ex
107
+ @logger.debug("CONNECT #{host}:#{port}: failed `#{ex.message}'")
108
+ res.set_error(ex)
109
+ raise WEBrick::HTTPStatus::EOFError
110
+ ensure
111
+ # At exit os variable sometimes can be nil which results in hanging forever
112
+ raise WEBrick::HTTPStatus::EOFError unless os
113
+
114
+ if handler = @config[:ProxyContentHandler]
115
+ handler.call(req, res)
116
+ end
117
+ res.send_response(ua)
118
+ access_log(@config, req, res)
119
+
120
+ # Should clear request-line not to send the response twice.
121
+ # see: HTTPServer#run
122
+ req.parse(NullReader) rescue nil
123
+ end
124
+
125
+ begin
126
+ while fds = IO::select([ua, os])
127
+ if fds[0].member?(ua)
128
+ buf = ua.readpartial(1024);
129
+ @logger.debug("CONNECT: #{buf.bytesize} byte from User-Agent")
130
+ os.write(buf)
131
+ elsif fds[0].member?(os)
132
+ buf = os.readpartial(1024);
133
+ @logger.debug("CONNECT: #{buf.bytesize} byte from #{host}:#{port}")
134
+ ua.write(buf)
135
+ end
136
+ end
137
+ rescue
138
+ os.close
139
+ @logger.debug("CONNECT #{host}:#{port}: closed")
140
+ end
141
+
142
+ raise WEBrick::HTTPStatus::EOFError
143
+ end
144
+ # rubocop:enable all
145
+ end
57
146
  end
58
147
  end
data/lib/ferrum/target.rb CHANGED
@@ -23,10 +23,12 @@ module Ferrum
23
23
  end
24
24
 
25
25
  def page
26
- @page ||= begin
27
- maybe_sleep_if_new_window
28
- Page.new(id, @browser)
29
- end
26
+ @page ||= build_page
27
+ end
28
+
29
+ def build_page(**options)
30
+ maybe_sleep_if_new_window
31
+ Page.new(id, @browser, **options)
30
32
  end
31
33
 
32
34
  def id
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ferrum
4
- VERSION = "0.12"
4
+ VERSION = "0.13"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ferrum
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.12'
4
+ version: '0.13'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Vorotilin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-13 00:00:00.000000000 Z
11
+ date: 2022-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -184,16 +184,19 @@ files:
184
184
  - lib/ferrum/browser/binary.rb
185
185
  - lib/ferrum/browser/client.rb
186
186
  - lib/ferrum/browser/command.rb
187
+ - lib/ferrum/browser/options.rb
187
188
  - lib/ferrum/browser/options/base.rb
188
189
  - lib/ferrum/browser/options/chrome.rb
189
190
  - lib/ferrum/browser/options/firefox.rb
190
191
  - lib/ferrum/browser/process.rb
191
192
  - lib/ferrum/browser/subscriber.rb
193
+ - lib/ferrum/browser/version_info.rb
192
194
  - lib/ferrum/browser/web_socket.rb
193
195
  - lib/ferrum/browser/xvfb.rb
194
196
  - lib/ferrum/context.rb
195
197
  - lib/ferrum/contexts.rb
196
198
  - lib/ferrum/cookies.rb
199
+ - lib/ferrum/cookies/cookie.rb
197
200
  - lib/ferrum/dialog.rb
198
201
  - lib/ferrum/errors.rb
199
202
  - lib/ferrum/frame.rb