bidi2pdf 0.1.2 → 0.1.4
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +29 -1
- data/CHANGELOG.md +36 -0
- data/cliff.toml +50 -26
- data/docker/Dockerfile.chromedriver +5 -0
- data/docker/entrypoint.sh +11 -1
- data/docker/nginx/default.conf +6 -0
- data/lib/bidi2pdf/bidi/add_headers_interceptor.rb +18 -21
- data/lib/bidi2pdf/bidi/auth_interceptor.rb +31 -38
- data/lib/bidi2pdf/bidi/browser_tab.rb +32 -52
- data/lib/bidi2pdf/bidi/client.rb +30 -57
- data/lib/bidi2pdf/bidi/command_manager.rb +50 -28
- data/lib/bidi2pdf/bidi/commands/add_intercept.rb +41 -0
- data/lib/bidi2pdf/bidi/commands/base.rb +73 -0
- data/lib/bidi2pdf/bidi/commands/browser_close.rb +15 -0
- data/lib/bidi2pdf/bidi/commands/browser_create_user_context.rb +15 -0
- data/lib/bidi2pdf/bidi/commands/browsing_context_close.rb +25 -0
- data/lib/bidi2pdf/bidi/commands/browsing_context_navigate.rb +31 -0
- data/lib/bidi2pdf/bidi/commands/browsing_context_print.rb +28 -0
- data/lib/bidi2pdf/bidi/commands/cancel_auth.rb +26 -0
- data/lib/bidi2pdf/bidi/commands/create_tab.rb +11 -0
- data/lib/bidi2pdf/bidi/commands/create_window.rb +32 -0
- data/lib/bidi2pdf/bidi/commands/get_user_contexts.rb +15 -0
- data/lib/bidi2pdf/bidi/commands/network_continue.rb +29 -0
- data/lib/bidi2pdf/bidi/commands/print_parameters_validator.rb +116 -0
- data/lib/bidi2pdf/bidi/commands/provide_credentials.rb +33 -0
- data/lib/bidi2pdf/bidi/commands/script_evaluate.rb +33 -0
- data/lib/bidi2pdf/bidi/commands/session_end.rb +15 -0
- data/lib/bidi2pdf/bidi/commands/session_status.rb +15 -0
- data/lib/bidi2pdf/bidi/commands/session_subscribe.rb +25 -0
- data/lib/bidi2pdf/bidi/commands/set_tab_cookie.rb +63 -0
- data/lib/bidi2pdf/bidi/commands/set_usercontext_cookie.rb +67 -0
- data/lib/bidi2pdf/bidi/commands.rb +27 -0
- data/lib/bidi2pdf/bidi/connection_manager.rb +16 -13
- data/lib/bidi2pdf/bidi/event_manager.rb +2 -0
- data/lib/bidi2pdf/bidi/interceptor.rb +75 -0
- data/lib/bidi2pdf/bidi/network_events.rb +0 -1
- data/lib/bidi2pdf/bidi/session.rb +141 -76
- data/lib/bidi2pdf/bidi/user_context.rb +25 -31
- data/lib/bidi2pdf/bidi/web_socket_dispatcher.rb +2 -0
- data/lib/bidi2pdf/chromedriver_manager.rb +23 -13
- data/lib/bidi2pdf/cli.rb +1 -3
- data/lib/bidi2pdf/launcher.rb +3 -1
- data/lib/bidi2pdf/version.rb +1 -1
- data/lib/bidi2pdf.rb +12 -0
- data/sig/bidi2pdf/bidi/command_manager.rbs +41 -0
- data/sig/bidi2pdf/bidi/commands/add_intercept.rbs +21 -0
- data/sig/bidi2pdf/bidi/commands/base.rbs +27 -0
- data/sig/bidi2pdf/bidi/commands/browser_close.rbs +9 -0
- data/sig/bidi2pdf/bidi/commands/browser_create_user_context.rbs +9 -0
- data/sig/bidi2pdf/bidi/commands/browsing_context_close.rbs +11 -0
- data/sig/bidi2pdf/bidi/commands/browsing_context_navigate.rbs +15 -0
- data/sig/bidi2pdf/bidi/commands/browsing_context_print.rbs +14 -0
- data/sig/bidi2pdf/bidi/commands/cancel_auth.rbs +11 -0
- data/sig/bidi2pdf/bidi/commands/create_tab.rbs +9 -0
- data/sig/bidi2pdf/bidi/commands/create_window.rbs +19 -0
- data/sig/bidi2pdf/bidi/commands/get_user_contexts.rbs +9 -0
- data/sig/bidi2pdf/bidi/commands/network_continue.rbs +19 -0
- data/sig/bidi2pdf/bidi/commands/print_parameters_validator.rbs +53 -0
- data/sig/bidi2pdf/bidi/commands/provide_credentials.rbs +15 -0
- data/sig/bidi2pdf/bidi/commands/script_evaluate.rbs +17 -0
- data/sig/bidi2pdf/bidi/commands/session_end.rbs +9 -0
- data/sig/bidi2pdf/bidi/commands/session_status.rbs +9 -0
- data/sig/bidi2pdf/bidi/commands/session_subscribe.rbs +15 -0
- data/sig/bidi2pdf/bidi/commands/set_tab_cookie.rbs +31 -0
- data/sig/bidi2pdf/bidi/commands/set_usercontext_cookie.rbs +27 -0
- data/sig/bidi2pdf/bidi/commands.rbs +6 -0
- data/sig/bidi2pdf/bidi/connection_manager.rbs +17 -0
- data/sig/bidi2pdf/bidi/interceptor.rbs +31 -0
- data/tasks/coverage.rake +16 -0
- metadata +65 -11
- data/lib/bidi2pdf/bidi/print_parameters_validator.rb +0 -114
- data/sig/bidi2pdf/bidi/print_parameters_validator.rbs +0 -44
- data/sig/bidi2pdf/chrome/chromedriver_downloader.rbs +0 -11
- data/sig/bidi2pdf/chrome/downloader_helper.rbs +0 -9
- data/sig/bidi2pdf/chrome/finder.rbs +0 -27
- data/sig/bidi2pdf/chrome/platform.rbs +0 -13
- data/sig/bidi2pdf/chrome/version_resolver.rbs +0 -19
@@ -10,143 +10,208 @@ require_relative "user_context"
|
|
10
10
|
module Bidi2pdf
|
11
11
|
module Bidi
|
12
12
|
class Session
|
13
|
-
SUBSCRIBE_EVENTS = [
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
"goog:cdp.CSS.styleSheetAdded",
|
20
|
-
"goog:cdp.Runtime.executionContextsCleared",
|
21
|
-
# Tracing
|
22
|
-
"goog:cdp.Tracing.tracingComplete",
|
23
|
-
"goog:cdp.Network.requestWillBeSent",
|
24
|
-
"goog:cdp.Debugger.scriptParsed",
|
25
|
-
"goog:cdp.Page.screencastFrame"
|
26
|
-
].freeze
|
27
|
-
|
28
|
-
attr_reader :session_uri, :started
|
29
|
-
|
30
|
-
def initialize(session_url:, headless: true)
|
13
|
+
SUBSCRIBE_EVENTS = %w[log script].freeze
|
14
|
+
DEFAULT_CHROME_ARGS = %w[--disable-gpu --disable-popup-blocking --disable-hang-monitor].freeze
|
15
|
+
|
16
|
+
attr_reader :session_uri, :started, :chrome_args
|
17
|
+
|
18
|
+
def initialize(session_url:, headless: true, chrome_args: DEFAULT_CHROME_ARGS)
|
31
19
|
@session_uri = URI(session_url)
|
32
20
|
@headless = headless
|
33
|
-
@client = nil
|
34
|
-
@browser = nil
|
35
|
-
@websocket_url = nil
|
36
21
|
@started = false
|
22
|
+
@chrome_args = chrome_args.dup
|
37
23
|
end
|
38
24
|
|
39
25
|
def start
|
26
|
+
return if started?
|
27
|
+
|
40
28
|
@started = true
|
41
29
|
client
|
30
|
+
rescue StandardError => e
|
31
|
+
@started = false
|
32
|
+
raise e
|
42
33
|
end
|
43
34
|
|
44
35
|
def client
|
45
|
-
@client ||=
|
46
|
-
end
|
47
|
-
|
48
|
-
def close
|
49
|
-
client&.send_cmd_and_wait("session.end", {}) do |response|
|
50
|
-
Bidi2pdf.logger.debug "Session ended: #{response}"
|
51
|
-
@client = nil
|
52
|
-
@websocket_url = nil
|
53
|
-
@browser = nil
|
54
|
-
end
|
36
|
+
@client ||= started? ? create_client : nil
|
55
37
|
end
|
56
38
|
|
57
39
|
def browser
|
58
40
|
@browser ||= create_browser
|
59
41
|
end
|
60
42
|
|
61
|
-
def
|
62
|
-
|
63
|
-
|
43
|
+
def close
|
44
|
+
return unless started?
|
45
|
+
|
46
|
+
2.times do |attempt|
|
47
|
+
client&.send_cmd_and_wait(Bidi2pdf::Bidi::Commands::SessionEnd.new, timeout: 1) do |response|
|
48
|
+
Bidi2pdf.logger.info "Session ended: #{response}"
|
49
|
+
|
50
|
+
cleanup
|
51
|
+
end
|
52
|
+
break
|
53
|
+
rescue CmdTimeoutError
|
54
|
+
Bidi2pdf.logger.error "Session end command timed out. Retrying... (#{attempt + 1})"
|
64
55
|
end
|
65
56
|
end
|
66
57
|
|
58
|
+
def user_contexts
|
59
|
+
send_cmd(Bidi2pdf::Bidi::Commands::GetUserContexts.new) { |resp| Bidi2pdf.logger.debug "User contexts: #{resp}" }
|
60
|
+
end
|
61
|
+
|
67
62
|
def status
|
68
|
-
|
69
|
-
|
70
|
-
|
63
|
+
send_cmd(Bidi2pdf::Bidi::Commands::SessionStatus.new) { |resp| Bidi2pdf.logger.info "Session status: #{resp.inspect}" }
|
64
|
+
end
|
65
|
+
|
66
|
+
def started?
|
67
|
+
@started
|
68
|
+
end
|
69
|
+
|
70
|
+
def websocket_url
|
71
|
+
return @websocket_url if @websocket_url
|
72
|
+
|
73
|
+
@websocket_url = if %w[ws wss].include?(session_uri.scheme)
|
74
|
+
session_uri.to_s
|
75
|
+
else
|
76
|
+
create_new_session
|
77
|
+
end
|
71
78
|
end
|
72
79
|
|
73
80
|
private
|
74
81
|
|
82
|
+
def send_cmd(command, &block)
|
83
|
+
client&.send_cmd_and_wait(command, &block)
|
84
|
+
end
|
85
|
+
|
86
|
+
# rubocop: disable Metrics/AbcSize
|
75
87
|
def create_browser
|
76
88
|
start
|
77
|
-
|
78
|
-
|
79
|
-
@client.wait_until_open
|
89
|
+
client.start
|
90
|
+
client.wait_until_open
|
80
91
|
|
81
92
|
Bidi2pdf.logger.info "Subscribing to events"
|
82
93
|
|
83
|
-
|
84
|
-
|
94
|
+
Bidi::Client.new(websocket_url).tap do |event_client|
|
95
|
+
event_client.start
|
96
|
+
event_client.wait_until_open
|
85
97
|
|
86
|
-
|
87
|
-
|
98
|
+
event_client.on_event(*SUBSCRIBE_EVENTS) do |data|
|
99
|
+
Bidi2pdf.logger.debug "Received event: #{data["method"]}, params: #{data["params"]}"
|
100
|
+
end
|
88
101
|
end
|
89
102
|
|
90
|
-
Bidi::Browser.new(
|
103
|
+
Bidi::Browser.new(client)
|
91
104
|
end
|
92
105
|
|
106
|
+
# rubocop: enable Metrics/AbcSize
|
107
|
+
|
93
108
|
def create_client
|
94
109
|
Bidi::Client.new(websocket_url).tap(&:start)
|
95
110
|
end
|
96
111
|
|
97
|
-
|
98
|
-
|
99
|
-
|
112
|
+
def create_new_session
|
113
|
+
session_data = exec_api_call(session_request)
|
114
|
+
Bidi2pdf.logger.debug "Session data: #{session_data}"
|
100
115
|
|
101
|
-
|
102
|
-
|
103
|
-
return @websocket_url
|
104
|
-
end
|
116
|
+
value = session_data["value"]
|
117
|
+
handle_error(value) if value.nil? || value["error"]
|
105
118
|
|
106
|
-
|
107
|
-
|
108
|
-
--disable-popup-blocking
|
109
|
-
--disable-hang-monitor
|
110
|
-
]
|
119
|
+
session_id = value["sessionId"]
|
120
|
+
ws_url = value["capabilities"]["webSocketUrl"]
|
111
121
|
|
112
|
-
|
122
|
+
Bidi2pdf.logger.info "Created session with ID: #{session_id}"
|
123
|
+
Bidi2pdf.logger.info "WebSocket URL: #{ws_url}"
|
124
|
+
ws_url
|
125
|
+
end
|
113
126
|
|
114
|
-
|
127
|
+
def session_request
|
128
|
+
session_chrome_args = chrome_args.dup
|
129
|
+
session_chrome_args << "--headless" if @headless
|
130
|
+
|
131
|
+
{
|
115
132
|
"capabilities" => {
|
116
133
|
"alwaysMatch" => {
|
117
134
|
"browserName" => "chrome",
|
118
|
-
"goog:chromeOptions" => {
|
119
|
-
"args" => args
|
120
|
-
},
|
135
|
+
"goog:chromeOptions" => { "args" => session_chrome_args },
|
121
136
|
"goog:prerenderingDisabled" => true,
|
122
|
-
"unhandledPromptBehavior" => {
|
123
|
-
default: "ignore"
|
124
|
-
},
|
137
|
+
"unhandledPromptBehavior" => { default: "ignore" },
|
125
138
|
"acceptInsecureCerts" => true,
|
126
139
|
"webSocketUrl" => true
|
127
140
|
}
|
128
141
|
}
|
129
142
|
}
|
143
|
+
end
|
130
144
|
|
131
|
-
|
145
|
+
def exec_api_call(payload)
|
146
|
+
response = Net::HTTP.post(session_uri, payload.to_json, "Content-Type" => "application/json")
|
147
|
+
body = response.body
|
148
|
+
code = response.code.to_i
|
132
149
|
|
133
|
-
|
134
|
-
|
150
|
+
if code != 200
|
151
|
+
log_api_error("Failed to create session", code, body)
|
152
|
+
return build_error("Session creation failed", "Response code: #{code}")
|
153
|
+
end
|
135
154
|
|
136
|
-
|
155
|
+
JSON.parse(body)
|
156
|
+
rescue StandardError => e
|
157
|
+
error_type = error_category(e)
|
158
|
+
build_error(error_type, "#{error_description(error_type)} #{e.message}", e.backtrace)
|
159
|
+
end
|
137
160
|
|
138
|
-
|
161
|
+
def log_api_error(message, code, body)
|
162
|
+
Bidi2pdf.logger.error "#{message}. Response code: #{code}"
|
163
|
+
Bidi2pdf.logger.error "Response body: #{body}"
|
164
|
+
end
|
139
165
|
|
140
|
-
|
141
|
-
|
166
|
+
def error_category(exception)
|
167
|
+
case exception
|
168
|
+
when Errno::ECONNREFUSED then "Connection refused"
|
169
|
+
when JSON::ParserError then "Invalid JSON response"
|
170
|
+
else "Unknown error"
|
171
|
+
end
|
172
|
+
end
|
142
173
|
|
143
|
-
|
144
|
-
|
174
|
+
def error_description(type)
|
175
|
+
{
|
176
|
+
"Connection refused" => "Could not connect to the session URL:",
|
177
|
+
"Invalid JSON response" => "Could not parse the response:",
|
178
|
+
"Unknown error" => "An unknown error occurred:"
|
179
|
+
}[type]
|
180
|
+
end
|
145
181
|
|
146
|
-
|
182
|
+
def build_error(error, message, backtrace = nil)
|
183
|
+
{
|
184
|
+
"value" => {
|
185
|
+
"error" => error,
|
186
|
+
"message" => message,
|
187
|
+
"stacktrace" => backtrace&.join("\n")
|
188
|
+
}.compact
|
189
|
+
}
|
147
190
|
end
|
148
191
|
|
149
|
-
|
192
|
+
def handle_error(value)
|
193
|
+
error = value["error"]
|
194
|
+
return unless error
|
195
|
+
|
196
|
+
msg = value["message"]
|
197
|
+
trace = value["stacktrace"]
|
198
|
+
|
199
|
+
Bidi2pdf.logger.error "Error: #{error} message: #{msg}"
|
200
|
+
Bidi2pdf.logger.error "Stacktrace: #{trace}" if trace
|
201
|
+
|
202
|
+
if msg =~ /probably user data directory is already in use/
|
203
|
+
Bidi2pdf.logger.info "Container detected with headless-only support, ensure xvfb is started" unless @headless
|
204
|
+
Bidi2pdf.logger.info "Check chromedriver permissions and --user-data-dir"
|
205
|
+
end
|
206
|
+
|
207
|
+
raise SessionNotStartedError,
|
208
|
+
"Session not started. Check logs for more details. Error: #{error} message: #{msg}"
|
209
|
+
end
|
210
|
+
|
211
|
+
def cleanup
|
212
|
+
@client&.close
|
213
|
+
@client = @websocket_url = @browser = nil
|
214
|
+
end
|
150
215
|
end
|
151
216
|
end
|
152
217
|
end
|
@@ -14,14 +14,16 @@ module Bidi2pdf
|
|
14
14
|
|
15
15
|
def context_id
|
16
16
|
@context_id ||= begin
|
17
|
-
|
18
|
-
|
19
|
-
end
|
17
|
+
res = client.send_cmd_and_wait(Bidi2pdf::Bidi::Commands::BrowserCreateUserContext.new) do |response|
|
18
|
+
raise "Error creating user context: #{response.inspect}" if response["error"]
|
20
19
|
|
21
|
-
|
20
|
+
response["result"]["userContext"]
|
21
|
+
end
|
22
22
|
|
23
|
-
|
24
|
-
|
23
|
+
Bidi2pdf.logger.debug "User context created: #{res.inspect}"
|
24
|
+
|
25
|
+
res
|
26
|
+
end
|
25
27
|
end
|
26
28
|
|
27
29
|
def set_cookie(
|
@@ -35,36 +37,28 @@ module Bidi2pdf
|
|
35
37
|
same_site: "strict",
|
36
38
|
ttl: 30
|
37
39
|
)
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
},
|
53
|
-
partition: {
|
54
|
-
type: "storageKey",
|
55
|
-
userContext: context_id,
|
56
|
-
sourceOrigin: source_origin
|
57
|
-
}
|
58
|
-
}) do |response|
|
40
|
+
cmd = Bidi2pdf::Bidi::Commands::SetUsercontextCookie.new(
|
41
|
+
user_context_id: context_id,
|
42
|
+
source_origin: source_origin,
|
43
|
+
name: name,
|
44
|
+
value: value,
|
45
|
+
domain: domain,
|
46
|
+
path: path,
|
47
|
+
secure: secure,
|
48
|
+
http_only: http_only,
|
49
|
+
same_site: same_site,
|
50
|
+
ttl: ttl
|
51
|
+
)
|
52
|
+
|
53
|
+
client.send_cmd_and_wait(cmd) do |response|
|
59
54
|
Bidi2pdf.logger.debug "Cookie set: #{response.inspect}"
|
60
55
|
end
|
61
56
|
end
|
62
57
|
|
63
58
|
def create_browser_window
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
}) do |response|
|
59
|
+
cmd = Bidi2pdf::Bidi::Commands::CreateWindow.new(user_context_id: context_id)
|
60
|
+
|
61
|
+
client.send_cmd_and_wait(cmd) do |response|
|
68
62
|
browsing_context_id = response["result"]["context"]
|
69
63
|
|
70
64
|
BrowserTab.new(client, browsing_context_id, context_id)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "chromedriver/binary"
|
4
|
+
require "securerandom"
|
4
5
|
|
5
6
|
module Bidi2pdf
|
6
7
|
class ChromedriverManager
|
@@ -55,9 +56,11 @@ module Bidi2pdf
|
|
55
56
|
|
56
57
|
close_session
|
57
58
|
|
58
|
-
|
59
|
+
debug_show_all_children
|
60
|
+
|
61
|
+
old_childprocesses = term_chromedriver
|
59
62
|
|
60
|
-
detect_zombie_processes
|
63
|
+
detect_zombie_processes old_childprocesses
|
61
64
|
|
62
65
|
return unless process_alive?
|
63
66
|
|
@@ -68,14 +71,10 @@ module Bidi2pdf
|
|
68
71
|
|
69
72
|
private
|
70
73
|
|
71
|
-
|
72
|
-
|
73
|
-
debug_show_all_children
|
74
|
+
def detect_zombie_processes(old_childprocesses)
|
75
|
+
Bidi2pdf.logger.debug "Old child processes for #{@pid}: #{old_childprocesses.map(&:pid).join(", ")}"
|
74
76
|
|
75
|
-
|
76
|
-
Bidi2pdf.logger.debug "Found child processes: #{child_processes.map(&:pid).join(", ")}"
|
77
|
-
|
78
|
-
zombie_processes = child_processes.select { |child| process_alive? child.pid }
|
77
|
+
zombie_processes = old_childprocesses.select { |child| process_alive? child.pid }
|
79
78
|
|
80
79
|
return if zombie_processes.empty?
|
81
80
|
|
@@ -83,9 +82,18 @@ module Bidi2pdf
|
|
83
82
|
printable_zombie_processes_str = printable_zombie_processes.join(", ")
|
84
83
|
|
85
84
|
Bidi2pdf.logger.error "Zombie Processes detected #{printable_zombie_processes_str}"
|
85
|
+
|
86
|
+
term_zombie_processes zombie_processes
|
86
87
|
end
|
87
88
|
|
88
|
-
|
89
|
+
def term_zombie_processes(zombie_processes)
|
90
|
+
Bidi2pdf.logger.info "Terminating zombie processes: #{zombie_processes.map(&:pid).join(", ")}"
|
91
|
+
|
92
|
+
zombie_processes.each do |child|
|
93
|
+
Bidi2pdf.logger.debug "Terminating PID #{child.pid} (#{child.name})"
|
94
|
+
Process.kill("TERM", child.pid)
|
95
|
+
end
|
96
|
+
end
|
89
97
|
|
90
98
|
def debug_show_all_children
|
91
99
|
Bidi2pdf::ProcessTree.new(@pid).traverse do |process, level|
|
@@ -103,9 +111,11 @@ module Bidi2pdf
|
|
103
111
|
end
|
104
112
|
|
105
113
|
def term_chromedriver
|
106
|
-
Bidi2pdf.
|
114
|
+
Bidi2pdf::ProcessTree.new(@pid).children(@pid).tap do |_child_processes|
|
115
|
+
Bidi2pdf.logger.info "Stopping Chromedriver (PID #{@pid})"
|
107
116
|
|
108
|
-
|
117
|
+
Process.kill("TERM", @pid)
|
118
|
+
end
|
109
119
|
rescue Errno::ESRCH
|
110
120
|
Bidi2pdf.logger.debug "Process already gone"
|
111
121
|
@pid = nil
|
@@ -131,7 +141,7 @@ module Bidi2pdf
|
|
131
141
|
|
132
142
|
def build_cmd
|
133
143
|
bin = Chromedriver::Binary::ChromedriverDownloader.driver_path
|
134
|
-
user_data_dir = File.join(Dir.tmpdir, "bidi2pdf", "user_data")
|
144
|
+
user_data_dir = File.join(Dir.tmpdir, "bidi2pdf", "user_data", SecureRandom.hex(8))
|
135
145
|
|
136
146
|
cmd = [bin]
|
137
147
|
cmd << "--port=#{@port}" unless @port.zero?
|
data/lib/bidi2pdf/cli.rb
CHANGED
@@ -122,7 +122,7 @@ module Bidi2pdf
|
|
122
122
|
end
|
123
123
|
|
124
124
|
def validate_print_options(opts)
|
125
|
-
Bidi2pdf::Bidi::PrintParametersValidator.validate!(opts)
|
125
|
+
Bidi2pdf::Bidi::Commands::PrintParametersValidator.validate!(opts)
|
126
126
|
rescue ArgumentError => e
|
127
127
|
raise Thor::Error, "Invalid print option: #{e.message}"
|
128
128
|
end
|
@@ -177,7 +177,6 @@ module Bidi2pdf
|
|
177
177
|
end
|
178
178
|
|
179
179
|
def launcher
|
180
|
-
# rubocop:disable Layout/BeginEndAlignment
|
181
180
|
@launcher ||= begin
|
182
181
|
username, password = parse_auth(merged_options[:auth]) if merged_options[:auth]
|
183
182
|
|
@@ -195,7 +194,6 @@ module Bidi2pdf
|
|
195
194
|
print_options: print_options
|
196
195
|
)
|
197
196
|
end
|
198
|
-
# rubocop:enable Layout/BeginEndAlignment
|
199
197
|
end
|
200
198
|
|
201
199
|
# rubocop:enable Metrics/AbcSize
|
data/lib/bidi2pdf/launcher.rb
CHANGED
@@ -21,6 +21,7 @@ module Bidi2pdf
|
|
21
21
|
@wait_network_idle = wait_network_idle
|
22
22
|
@print_options = print_options || {}
|
23
23
|
@remote_browser_url = remote_browser_url
|
24
|
+
@custom_session = nil
|
24
25
|
end
|
25
26
|
|
26
27
|
# rubocop:enable Metrics/ParameterLists
|
@@ -42,13 +43,14 @@ module Bidi2pdf
|
|
42
43
|
|
43
44
|
def stop
|
44
45
|
@manager&.stop
|
46
|
+
@custom_session&.close
|
45
47
|
end
|
46
48
|
|
47
49
|
private
|
48
50
|
|
49
51
|
def session
|
50
52
|
if @remote_browser_url
|
51
|
-
Bidi::Session.new(session_url: @remote_browser_url, headless: @headless)
|
53
|
+
@custom_session = Bidi::Session.new(session_url: @remote_browser_url, headless: @headless)
|
52
54
|
else
|
53
55
|
@manager = ChromedriverManager.new(port: @port, headless: @headless)
|
54
56
|
@manager.start
|
data/lib/bidi2pdf/version.rb
CHANGED
data/lib/bidi2pdf.rb
CHANGED
@@ -10,6 +10,18 @@ require "logger"
|
|
10
10
|
module Bidi2pdf
|
11
11
|
class Error < StandardError; end
|
12
12
|
|
13
|
+
class SessionNotStartedError < Error; end
|
14
|
+
|
15
|
+
class WebsocketError < Error; end
|
16
|
+
|
17
|
+
class ClientError < WebsocketError; end
|
18
|
+
|
19
|
+
class CmdError < ClientError; end
|
20
|
+
|
21
|
+
class CmdResponseNotStoredError < ClientError; end
|
22
|
+
|
23
|
+
class CmdTimeoutError < ClientError; end
|
24
|
+
|
13
25
|
@logger = Logger.new($stdout)
|
14
26
|
@logger.level = Logger::DEBUG
|
15
27
|
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Bidi2pdf
|
2
|
+
module Bidi
|
3
|
+
class CommandManager
|
4
|
+
self.@id: untyped
|
5
|
+
|
6
|
+
self.@id_mutex: untyped
|
7
|
+
|
8
|
+
@socket: untyped
|
9
|
+
|
10
|
+
@logger: untyped
|
11
|
+
|
12
|
+
@pending_responses: untyped
|
13
|
+
|
14
|
+
@initiated_cmds: untyped
|
15
|
+
|
16
|
+
def self.initialize_counter: () -> untyped
|
17
|
+
|
18
|
+
def self.next_id: () -> untyped
|
19
|
+
|
20
|
+
def initialize: (untyped socket, logger: untyped) -> void
|
21
|
+
|
22
|
+
def send_cmd: (untyped cmd, ?store_response: bool) -> untyped
|
23
|
+
|
24
|
+
def send_cmd_and_wait: (untyped cmd, ?timeout: untyped) ?{ (untyped) -> untyped } -> untyped
|
25
|
+
|
26
|
+
def pop_response: (untyped id, timeout: untyped) -> untyped
|
27
|
+
|
28
|
+
def handle_response: (untyped data) -> (true | untyped | false)
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def init_queue_for: (untyped id) -> untyped
|
33
|
+
|
34
|
+
def next_id: () -> untyped
|
35
|
+
|
36
|
+
def redact_sensitive_fields: (untyped obj, ?::Array[untyped] sensitive_keys) -> untyped
|
37
|
+
|
38
|
+
def raise_timeout_error: (untyped id, untyped cmd) -> untyped
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Bidi2pdf
|
2
|
+
module Bidi
|
3
|
+
module Commands
|
4
|
+
class AddIntercept
|
5
|
+
include Base
|
6
|
+
|
7
|
+
BEFORE_REQUEST: String
|
8
|
+
RESPONSE_STARTED: String
|
9
|
+
AUTH_REQUIRED: String
|
10
|
+
|
11
|
+
@context: String
|
12
|
+
@phases: Array[String]
|
13
|
+
@url_patterns: Array[String]
|
14
|
+
|
15
|
+
def initialize: (context: String, phases: Array[String], url_patterns: Array[String]) -> void
|
16
|
+
|
17
|
+
def validate_phases!: () -> void
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Bidi2pdf
|
2
|
+
module Bidi
|
3
|
+
module Commands
|
4
|
+
module Base
|
5
|
+
def method_name: () -> String
|
6
|
+
|
7
|
+
def params: () -> Hash[Symbol, untyped]
|
8
|
+
|
9
|
+
def as_payload: (untyped id) -> Hash[Symbol, untyped]
|
10
|
+
|
11
|
+
def ==: (untyped other) -> bool
|
12
|
+
|
13
|
+
def eql?: (untyped other) -> bool
|
14
|
+
|
15
|
+
def hash: () -> Integer
|
16
|
+
|
17
|
+
def inspect: () -> String
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def redact_sensitive_fields: (untyped obj, Array[String] sensitive_keys) -> untyped
|
22
|
+
|
23
|
+
def raise_timeout_error: (untyped id, String method, Hash[Symbol, untyped] params) -> void
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|