bidi2pdf 0.1.0 → 0.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7d773a323c63404e1c8dee00d180e6f774f5b45c33e59bc759b8186d3398aeed
4
- data.tar.gz: 9b3452ac73398cc6037ca3d39b792afafbd2dfd47e55e3fe0c69783627b7fc88
3
+ metadata.gz: a67b40e096dd2b6b73fa65cec7d9d75182b995435c17186d755f89efebb2ab26
4
+ data.tar.gz: fde0861d58dd30788aa1b54a24d956d3438bd83cc08a5ec9d22e6750a3e646d6
5
5
  SHA512:
6
- metadata.gz: e656e92c5a4aa8a82ab3d0dde12fdf3cd4a8743ab8dd47a77d229452e5ab0127f40ed5ee84c02c190bb35aed5de7fe14696d30b22de0bc9966cdb9fd94eaf9b9
7
- data.tar.gz: 57b04e9c98c91e12ccfb432d292f13186f9a92776a81847736719843dffeed1d07adab9d32dd858709aa9803b8ac476c38cbfc9a87bbed5fc6ce88efec599ecd
6
+ metadata.gz: 52e199c72b902e046140e6d47a9b00a8354e53a88f3af6135f0d7ab587c7d59532a904388e4a62ed4ba29c03609eab3b8c7f3aea0aa131ba8880f8ecb6f9a503
7
+ data.tar.gz: a83f7091a455e5c8cb5f2b7e8e621c044b2184c2c6e5a6e11aaa4f4ca2f9879ada89eb7951e7ad78e07a2d473396bb529ce5c4dfc771130a40a1977bb6e60575
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.1.1] - 2025-04-01
4
+
5
+ ### Added
6
+
7
+ - Docker Compose setup with Nginx for authentication examples
8
+ - Sample configurations for different authentication methods:
9
+ - Basic HTTP authentication
10
+ - Cookie-based authentication
11
+ - API key header authentication
12
+
13
+ ### Fixed
14
+
15
+ - HTTP cookie handling issues
16
+
3
17
  ## [0.1.0] - 2025-03-26
4
18
 
5
19
  - Initial release
data/README.md CHANGED
@@ -91,6 +91,27 @@ docker run -it --rm -v ./output:/reports bidi2pdf \
91
91
  bidi2pdf render --url=https://example.com --output /reports/example.pdf
92
92
  ```
93
93
 
94
+ ### Test it with docker compose
95
+
96
+ ```bash
97
+ docker compose -f docker/docker-compose.yml up -d
98
+
99
+ # simple example
100
+ docker compose -f docker/docker-compose.yml exec app bidi2pdf render --url=http://nginx/sample.html --wait_window_loaded --wait_network_idle --output /reports/simple.pdf
101
+
102
+ # basic auth example
103
+ docker compose -f docker/docker-compose.yml exec app bidi2pdf render --url=http://nginx/basic/sample.html --auth admin:secret --wait_window_loaded --wait_network_idle --output /reports/basic.pdf
104
+
105
+ # header example
106
+ docker compose -f docker/docker-compose.yml exec app bidi2pdf render --url=http://nginx/header/sample.html --header "X-API-KEY=secret" --wait_window_loaded --wait_network_idle --output /reports/header.pdf
107
+
108
+ # cookie example
109
+ docker compose -f docker/docker-compose.yml exec app bidi2pdf render --url=http://nginx/cookie/sample.html --cookie "auth=secret" --wait_window_loaded --wait_network_idle --output /reports/cookie.pdf
110
+
111
+
112
+ docker compose -f docker/docker-compose.yml down
113
+ ```
114
+
94
115
  ## Configuration Options
95
116
 
96
117
  | Option | Description |
@@ -1 +1,18 @@
1
1
  name: bidi2pdf
2
+ services:
3
+ nginx:
4
+ image: nginx:1.27-bookworm
5
+ ports:
6
+ - "9091:80"
7
+ volumes:
8
+ - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
9
+ - ./nginx/htpasswd:/etc/nginx/conf.d/.htpasswd
10
+ - ../spec/fixtures:/var/www/html
11
+
12
+ app:
13
+ build:
14
+ context: ..
15
+ dockerfile: docker/Dockerfile
16
+ volumes:
17
+ - ../tmp/reports:/reports
18
+ command: tail -f /dev/null
@@ -0,0 +1,42 @@
1
+ log_format with_headers_and_cookies '
2
+ $remote_addr - $remote_user [$time_local] "$request" '
3
+ 'status=$status body_bytes_sent=$body_bytes_sent '
4
+ 'cookie="$http_cookie" '
5
+ 'ua="$http_user_agent" '
6
+ 'referer="$http_referer" '
7
+ 'custom-header-x="$http_x_custom_header" ';
8
+
9
+ server {
10
+ # error_log /var/log/nginx/error.log debug;
11
+ access_log /var/log/nginx/access.log with_headers_and_cookies;
12
+
13
+ location / {
14
+ root /var/www/html;
15
+ }
16
+
17
+ location /basic {
18
+ alias /var/www/html;
19
+ try_files $uri $uri/ =404;
20
+
21
+ auth_basic "Restricted Area";
22
+ auth_basic_user_file /etc/nginx/conf.d/.htpasswd;
23
+ }
24
+
25
+ location /cookie {
26
+ alias /var/www/html;
27
+ try_files $uri $uri/ =404;
28
+
29
+ if ($cookie_auth != "secret") {
30
+ return 403;
31
+ }
32
+ }
33
+
34
+ location /header {
35
+ alias /var/www/html;
36
+ try_files $uri $uri/ =404;
37
+
38
+ if ($http_x_api_key != "secret") {
39
+ return 403;
40
+ }
41
+ }
42
+ }
@@ -0,0 +1 @@
1
+ admin:$apr1$wwl1dIH7$Pm2PaGHWNnXhCoLzD1gr2/
@@ -42,6 +42,8 @@ module Bidi2pdf
42
42
 
43
43
  term_chromedriver
44
44
 
45
+ detect_zombie_processes
46
+
45
47
  return unless process_alive?
46
48
 
47
49
  kill_chromedriver timeout: timeout
@@ -51,6 +53,33 @@ module Bidi2pdf
51
53
 
52
54
  private
53
55
 
56
+ # rubocop:disable Metrics/AbcSize
57
+ def detect_zombie_processes
58
+ debug_show_all_children
59
+
60
+ child_processes = Bidi2pdf::ProcessTree.new(@pid).children(@pid)
61
+ Bidi2pdf.logger.debug "Found child processes: #{child_processes.map(&:pid).join(", ")}"
62
+
63
+ zombie_processes = child_processes.select { |child| process_alive? child.pid }
64
+
65
+ return if zombie_processes.empty?
66
+
67
+ printable_zombie_processes = zombie_processes.map { |child| "#{child.name}:#{child.pid}" }
68
+ printable_zombie_processes_str = printable_zombie_processes.join(", ")
69
+
70
+ Bidi2pdf.logger.error "Zombie Processes detected #{printable_zombie_processes_str}"
71
+ end
72
+
73
+ # rubocop:enable Metrics/AbcSize
74
+
75
+ def debug_show_all_children
76
+ Bidi2pdf::ProcessTree.new(@pid).traverse do |process, level|
77
+ indent = " " * level
78
+ prefix = level.zero? ? "" : "└─ "
79
+ Bidi2pdf.logger.debug "#{indent}#{prefix}PID #{process.pid} (#{process.name})"
80
+ end
81
+ end
82
+
54
83
  def close_session
55
84
  Bidi2pdf.logger.info "Closing session"
56
85
 
@@ -126,8 +155,8 @@ module Bidi2pdf
126
155
 
127
156
  # rubocop: enable Metrics/AbcSize
128
157
 
129
- def process_alive?
130
- return false unless @pid
158
+ def process_alive?(pid = @pid)
159
+ return false unless pid
131
160
 
132
161
  begin
133
162
  Process.waitpid(@pid, Process::WNOHANG)
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "sys/proctable"
4
+ module Bidi2pdf
5
+ class ProcessTree
6
+ include Sys
7
+
8
+ def initialize(root_pid = nil)
9
+ @root_pid = root_pid
10
+ @process_map = build_process_map
11
+ connect_children
12
+ end
13
+
14
+ def children(of_pid)
15
+ return [] unless @process_map[of_pid]
16
+
17
+ direct_children = @process_map[of_pid][:children].map do |child_pid|
18
+ @process_map[child_pid][:info]
19
+ end
20
+
21
+ (direct_children + direct_children.flat_map { |child| children(child.pid) }).uniq
22
+ end
23
+
24
+ def traverse(&handler)
25
+ handler = method(:print_handler) unless handler.is_a?(Proc)
26
+
27
+ root_pids.each { |pid| traverse_branch(pid, &handler) }
28
+ end
29
+
30
+ private
31
+
32
+ def print_handler(process, level)
33
+ indent = " " * level
34
+ prefix = level.zero? ? "" : "└─ "
35
+ puts "#{indent}#{prefix}PID #{process.pid} (#{process.name})"
36
+ end
37
+
38
+ def build_process_map
39
+ ProcTable.ps.each_with_object({}) do |process, map|
40
+ map[process.pid] = { info: process, children: [] }
41
+ end
42
+ end
43
+
44
+ def connect_children
45
+ @process_map.each_value do |entry|
46
+ parent_pid = entry[:info].ppid
47
+ @process_map[parent_pid][:children] << entry[:info].pid if parent_pid && @process_map.key?(parent_pid)
48
+ end
49
+ end
50
+
51
+ def root_pids
52
+ return [@root_pid] if @root_pid
53
+
54
+ @process_map.values
55
+ .select { |entry| entry[:info].ppid.nil? || !@process_map.key?(entry[:info].ppid) }
56
+ .map { |entry| entry[:info].pid }
57
+ end
58
+
59
+ def traverse_branch(pid, level = 0, &handler)
60
+ return unless @process_map[pid]
61
+
62
+ process = @process_map[pid][:info]
63
+
64
+ handler.call(process, level)
65
+
66
+ @process_map[pid][:children].each do |child_pid|
67
+ traverse_branch(child_pid, level + 1, &handler)
68
+ end
69
+ end
70
+ end
71
+ end
@@ -29,25 +29,25 @@ module Bidi2pdf
29
29
  browser = @session.browser
30
30
  user_context = browser.create_user_context
31
31
 
32
- add_cookies(user_context)
33
-
34
32
  window = user_context.create_browser_window
35
33
  tab = window.create_browser_tab
36
34
 
37
35
  @window = window
38
36
  @tab = tab
39
37
 
38
+ add_cookies(tab)
39
+
40
40
  add_headers
41
41
  add_basic_auth
42
42
  end
43
43
 
44
- def add_cookies(user_context)
44
+ def add_cookies(tab)
45
45
  @cookies.each do |name, value|
46
- user_context.set_cookie(
46
+ tab.set_cookie(
47
47
  name: name,
48
48
  value: value,
49
49
  domain: domain,
50
- source_origin: source_origin
50
+ secure: uri.scheme == "https"
51
51
  )
52
52
  end
53
53
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bidi2pdf
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
data/lib/bidi2pdf.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "bidi2pdf/utils"
4
+ require_relative "bidi2pdf/process_tree"
4
5
  require_relative "bidi2pdf/launcher"
5
6
  require_relative "bidi2pdf/bidi/session"
6
7
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bidi2pdf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dieter S.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-04-02 00:00:00.000000000 Z
11
+ date: 2025-04-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '2.4'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sys-proctable
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.3'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.3'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: thor
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -267,6 +281,8 @@ files:
267
281
  - Rakefile
268
282
  - docker/Dockerfile
269
283
  - docker/docker-compose.yml
284
+ - docker/nginx/default.conf
285
+ - docker/nginx/htpasswd
270
286
  - exe/bidi2pdf
271
287
  - lib/bidi2pdf.rb
272
288
  - lib/bidi2pdf/bidi/add_headers_interceptor.rb
@@ -284,6 +300,7 @@ files:
284
300
  - lib/bidi2pdf/chromedriver_manager.rb
285
301
  - lib/bidi2pdf/cli.rb
286
302
  - lib/bidi2pdf/launcher.rb
303
+ - lib/bidi2pdf/process_tree.rb
287
304
  - lib/bidi2pdf/session_runner.rb
288
305
  - lib/bidi2pdf/utils.rb
289
306
  - lib/bidi2pdf/version.rb